Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.10.2015, 19:47   #1
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию Необходима помощь в понимании сокетов

Ребят помогите разобраться! что то я совсем не пойму...
Вот Вы мне объясните. Мне необходимо принимать поток байт преобразовывать их в определенном порядке и писать эти данные в базу данных.

Прочитал есть блокирующий режим сокетов и асинхронный режим сокетов, почему то я решил, что блокирующий режим не совсем подходит для моего случая, да и вообще не для винды он, либо он упрется в предел по потокам, вобще я хочу сделать многопоточное приложение.
Подумал я и решил выбрать асинхронный подход, правильно ли?
Прочитал так же, что при асинхронном расширении сокета, программисты создают множество окон для каждого соединения, создание потоков не имеет смысла в этом режиме.

так вот собственно вопрос
если я буду использовать прием данных в основном потоке, то блокирования интерфейса не будет, но в момент записи принятой информации в бд, который тоже будет производится в основном потоке будет блокироваться интерфейс. Значит для того что бы интерфейс не блокировался в момент записи, нужно производить запись в бд в отдельном потоке?

получается что все данные в асинхронном режиме принимаем в основной поток, при чем может быть и несколько разных принимающих портов по каждому из которых может приниматься разные протоколы, и потом создаем отдельные потоки для отправки инфы в бд. Правильно ли я думаю
Antony41 вне форума Ответить с цитированием
Старый 16.10.2015, 20:15   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Правильно ли я думаю
Неа. Хочешь добрый совет? - Используй INDY.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 16.10.2015, 20:44   #3
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

Не знаю, но чем то меня Indy пугают, вобще я как то писал приложение на чистом winsock с поддержкой асинхронного расширения, но я делал, как то не совсем я считаю правильно. Хотелось бы понять именно глубину сути на чистом winsocket API.

Я понимаю так для того чтобы не блокировался интерфейс главного потока, необходимо выполнять операцию приема данных в отдельном потоке, но тогда в потоке придется создать невидимое окно, а так же реализовать в потоке цикл обработки сообщений, типа
Код:
While not Terminated Do Begin
        res := Integer( GetMessage(Msg, 0, 0, 0 ));
        If (res = -1 )or (res = 0) then
          exit  //
        else begin
          TranslateMessage( Msg );
          DispatchMessage( Msg );
        end;
Короче хрень какая то, я просто запутался
мне просто нужно принимать разные потоки данных расшифровать их по определенному протоколу и сохранить инфу в базу
Antony41 вне форума Ответить с цитированием
Старый 16.10.2015, 20:59   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Я понимаю так для того чтобы не блокировался интерфейс главного потока, необходимо выполнять операцию приема данных в отдельном потоке
Блокирование потока производится при ожидании при чтении функцией recv() и прослушке функцией accept(), если мне память не изменяет. Компенсировать это можно доппотоком. Так же можно использовать примерно такую схему:
Код:
while true do begin
 if select(Тут устновка таймаута прослушки) then 
   accept(...);
 Application.ProcessMessages();
end;
А при использовании recv() цикл примерно такого содержания:
Код:
var buf:array[1..FPBufferSize] of byte; ReadedSize,BytesInSocket:Cardinal;
begin
 Result:=0; Data.Clear; Data.Position:=0;
 repeat
    if ioctlsocket(AcceptedSocket,FIONREAD,BytesInSocket)<>SOCKET_ERROR then begin
     if BytesInSocket>0 then begin
      FillChar(buf,Sizeof(buf),0);
      ReadedSize:=fprecv(AcceptedSocket,@buf,sizeof(buf),0);
      Result:=Result+ReadedSize;
      Data.Write(buf,ReadedSize);
     end;
    end;
 until (BytesInSocket=0);
end;
Где Data - TStream какой-то.

Эти два механизма позволят соблюдать неблокирующий режим в любом потоке.
Цитата:
но тогда в потоке придется создать невидимое окно
Никакой связи никакие окна к потокам и тем более сокетам не имеют.
Я к примеру предпочитаю описать TThread, в которых и запускаю циклы, подобные описанным выше.
Цитата:
Короче хрень какая то, я просто запутался
Вот потому и возьми Индейку, там все это уже реализовано - тамошние события ничего не блокируют (а если блокируют, всегда можно кинуть компонент idAntifreeze).
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 16.10.2015, 21:40   #5
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

такая как я считал простая задача так тяжело дается. Я уж подумываю на C# и .NET перейти, хотя api он есть апи... Stilet на счет INDY все равно какие то сомнения в сторону их косяков, боюсь столкнусь с какой то ошибкой, и кирдык грабли, где то я на это уже натыкался, вот ты сам что бы выбрал? я все таки хочу понять как использовать асинхронный сокет в потоках, или запись в базу нужно в потоках использовать, чтоб одновременно можно было принимать разные потоки байт по разным протоколам (не путать с TCP UDP), расшифровать и записать в БД

Ведь вышеприведенный пример как я понимаю это блокирующий сокет с доп потоком проверки состояния на зависание, в котором в цикле производился вызов select. На сколько я читал такой метод не очень хорошо распоряжается ресурсами компа, тоесть заряжает проц даже когда ни каких данных не поступает

Последний раз редактировалось Аватар; 16.10.2015 в 22:32.
Antony41 вне форума Ответить с цитированием
Старый 17.10.2015, 07:01   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
Я уж подумываю на C# и .NET перейти
Ну вполне хороший выбор.
Цитата:
боюсь столкнусь с какой то ошибкой, и кирдык грабли
Ты уже кирдык-грабли столкнулся )))
Какая разница, во что упереться? Все равно придется какие-то проблемы решать чем бы не пользовался.
Цитата:
вот ты сам что бы выбрал?
Я и инди и сокеты использую. Они у меня так вот удобно сочетаются в проектах.
Цитата:
вышеприведенный пример как я понимаю это блокирующий сокет
Почему блокирующий? Там же проверка на доступность данных в сокете есть. Он ниче не блокирует.
Цитата:
На сколько я читал такой метод не очень хорошо распоряжается ресурсами компа, тоесть заряжает проц даже когда ни каких данных не поступает
Бред какой-то... Ты где сие крамольство читал?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 17.10.2015, 10:38   #7
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

хорошо спасибо Stilet попробую на инди набросать, пошел изучать
Antony41 вне форума Ответить с цитированием
Старый 21.10.2015, 00:13   #8
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

Не хотелось бы создавать новую тему...
В общем прочитал я про инди, и накидал сервак.
Есть сервер который постоянно транслирует данные по собственному протоколу, порядок примерно такой:
подключение...
непрерывный поток данных начат
кол-во пакетов (Int)(4 байта)
пакет№1
длина серийного номера(Byte)(1 байт)
серийный номер (string)(N байт)
и тд.
пакет№2
длина серийного номера(Int)
серийный номер (string)(N байт)
и тд.
пакет№3
длина серийного номера(Int)
серийный номер (string)(N байт)
и тд.
и тд.
Снова кол-во пакетов
пакет№1
длина серийного номера(Byte)(1 байт)
серийный номер (string)(N байт)
и тд.
пакет№2
длина серийного номера(Int)
серийный номер (string)(N байт)
и тд.
пакет№3
длина серийного номера(Int)
серийный номер (string)(N байт)
и тд.
и тд.

Далее идет ответ от сервера приема данных Hex $55 (тот который я пишу), если подтверждения нет, то сервер трансляции разрывает соединение и поторяет попытку отправки данных.

В общем мне нужно чтоб сервак приема данных был устойчив к сбоям и можно было примать одновременно несколько ретрансляций.

Понимаю, что работа идет в потоках, но ни как не могу понять что я сделал не так. Вываливается страшнейший AV.

Призываю к помощи и просьба ткнуть носом в свой косяк.
Привожу весь код так как ограничения форума не позволяют вставить более 5000 символов.
[/CODE]
Вложения
Тип файла: zip 1.zip (435.8 Кб, 8 просмотров)
Antony41 вне форума Ответить с цитированием
Старый 21.10.2015, 18:05   #9
Antony41
Пользователь
 
Аватар для Antony41
 
Регистрация: 20.03.2009
Сообщений: 99
По умолчанию

в момент приема данных всё ок, но когда я принудительно останавливаю передачу потока данных на сервере ретрансляции, то на сервере приема вываливается Connection Closed Gracefully и затем AV
Antony41 вне форума Ответить с цитированием
Старый 21.10.2015, 19:21   #10
come-on
Участник клуба
 
Регистрация: 21.10.2015
Сообщений: 1,361
По умолчанию

Используйте try блоки
come-on вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Нужна помощь в понимании программы, написанной на С baltushka Помощь студентам 11 06.10.2011 00:50
Необходима помощь Sambuko Общие вопросы C/C++ 5 21.09.2009 13:20
Необходима помощь mrwhat Фриланс 7 19.05.2009 09:03
Необходима помощь nimf Свободное общение 0 29.08.2007 10:43