![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
![]() Добрый день, уважаемые программисты! Опишу вкратце решаемую задачу.
Необходим сервер приема данных (текстовые сообщения в 15-20 строк). Данные отправляют клиенты (устройства, которые связываются с сервером по каналу GPRS). Всего их 2000-2500 шт., каждый отправляет сообщение 1 раз в 5 минут, соответственно на сервер примерно 5-20 обращений в секунду. Принятое сообщение необходимо поместить в Memo. Вроде бы задача в 3 строки, но корректно настроить работу сервера не удается. Пошел сначала простым и неправильным путём: 1. ServerSocket в режиме stNonBlocking Код:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket); begin {От клиента получено сообщение - выводим его в Memo1} Memo2.Lines.Insert(0,'Message received from client'); Memo1.Lines.Insert(0,'> '+Socket.ReceiveText); if RadioButton1.Checked then begin ServerSocket1.Socket.Connections[0].SendText('OK'); ServerSocket1.Socket.Connections[0].Close; end; end; соединение появляется раньше, чем происходит запись принятого текста. То есть все сообщения принимаются, но принимаются они "урезанными". Ах да, забыл написать, что клиенту после приема от него сообщения надо отправить "OK", чтобы устройство знало, что пакет принят и можно отключаться. 2. Было принято решение использовать сервер (как вы уже догадались=)) в режиме stThreadBlocking. При небольшом количестве клиентов все работает прекрасно (вообщем то как и первый вариант), но при количестве 2000-2500 клиентов сообщения в Memo вообще пишутся пустыми, и только изредка там появляется 1-2 строки от клиента, но этого, само собой, не достаточно. Вот код: Код:
//описываем класс type TServerThread = class(TServerClientThread) procedure ClientExecute; override; end; //описываем процедуру, которая будет срабатывать при запуске "нити" procedure TServerThread.ClientExecute; var i:integer; begin Form1.Memo1.Lines.Insert(0,'> '+ClientSocket.ReceiveText); ClientSocket.SendText('OK'); ClientSocket.Close; Terminate; end; ... procedure TForm1.ServerSocket1GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread); begin Memo2.Lines.Insert(0,'Get Thread'); //создаем экземпляр класса с приоритетом реального времени SocketThread:=TServerThread.Create(true, ClientSocket); SocketThread.Priority:=tpTimeCritical; SocketThread.Resume; end; TServerThread.ClientExecute нужно что-то дописать, чтобы сервер ждал полного сообщения от клиента, а уже потом отсылал ему "OK" и закрывал соединение. Финальная строка в тексте, полученном от клиента, всегда начинается с "REND"... p.s. не забываем, что клиенты работают по gprs, соединение соответственно не "самолёт"... Заранее спасибо! |
#2
|
||||
|
||||
![]() Цитата:
1. сообщение наверняка бьется на несколько. поэтому будут выводится части сообщений вперемешку от всех клиентов. т.е. нужно части сообщения группировать по клиентам и накапливать их перед выводом. и почему то ответ всегда идет только первому клиенту. 2. нельзя из потока непосредственно писать в VCL визуальные объекты. читаем про Synchronize. Пишу программы за еду. __________________ |
#3
|
|||
|
|||
![]() Цитата:
Цитата:
То есть мне надо понять, что мне добавить в код, чтобы в конкретном потоке принимался полный текст от устройства. Также пока не представляю как буду передавать принятый ПОЛНОСТЬЮ пакет в другой поток для парсинга. Вообщем для начала надо разобраться с приемом данных, а потом уже идти далее. |
#4
|
||||
|
||||
![]() Цитата:
Пишу программы за еду. __________________ |
#5
|
|||
|
|||
![]() Цитата:
|
#6
|
||||
|
||||
![]() как уже написал выше, всегда нужно быть готовым к тому, что длинное сообщение, отправленное клиентом, может разбиться на несколько. т.е. одно сообщение закончиться на $RE, а следующее начаться на ND. выход для событийной модели: "склеивать" все сообщения по каждому клиенту и проверять его конец на $REND. но наверное это удобней делать на блокируемом сокете в потоке. проще организовать свой клиентский буфер.
Пишу программы за еду. __________________ |