Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Точное определение момента, когда можно отправлять текст в сокет [D5, WinXP]


Страницы:   1 2

VID ©   (2004-05-31 02:12:00) 

Я долго мучался, но так ничего и не смог придумать. Дело такое:
необходимо от сервера клиенту послать ну скажем 1000 сообщений (через Socket.SendText), причём длина отправляемого текста - большая.

В-общем получается что то вроде
for i := 1 to 1000 do Socket.SendText(S);

Так вот до клиента приходит как правило только половина отправленных сообщений.

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

Как я понимаю решение проблемы должно выглядеть следующим образом:
for i:=1 to 1000 do
begin
 Socket.SendText(S);
 {и здесь ждём столько времени сколько необходимо что бы не возникло ситуации с перегрузкой вызовами этого метода }
end;

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

Брать  какие то константы типа
x:=gettickcount;
while gettickcount - x < 100 do application.processmessages;
я не хочу, т.к. хоть это и срабатывает на моём компе, но не факт что сработает на более медленном.

как быть ?


atruhin   (2004-05-31 06:01:00) [21]

>Evgeny V - на сайте есть куча стотей по сокетам, отдельно по компонентам TClienSocket, TServerSocket. Почитай а то у тебя такая каша получилась.


Evgeny V   (2004-05-31 05:47:00) [22]


> Piter ©   (31.05.04 03:32) [5]
> Делаешь так:
>
> вызываешь Socket.SendText
>
> он тебе возвращает сколько символов отправлено.
>
> 1)Если отправлено столько, сколько передавал - все нормально,
> идешь дальше.
> 2) если отправилось меньше - то запоминашь какие символы
> не отправились и отправляешь их при возниконовении события
> OnClientWrite

Cогдасен, но увы у меня вот OnClientWrite не всегда возникает, один раз только
(и не только у меня, но и у коллег на работе та же проблема), пробовал на просто АПИ сокетах в модели EventSelect, то же самое, FD_WRITE возникает на моей машине только один раз, при первом входе в WSAWaitForMultipleEvents. Это и в дельфи 5 и в дельфи 6 наблюдается с клиентским и серверным сокетоми В ОС 98 и XP. Интересно было бы, что бы кто подсказал в чем проблема? Я это дело конечно обошел через перекрытый ввод/вывод, WsaSend(FSocket,@WBufferW,1,ByteWr,FlagsW,@WriteE,nil); где WriteE - OVERLAPPED структура, по чтению так же делаю, хотя событие на него возникает нормально и регулярно. Так и вот и смещиваю две модели, EventSelect для событий FD_CLOSE, FD_CONNECT и OVERLAPPED для событий чения и записи. Кто знает причину - поделитесь, буду признателен:-)


Piter   (2004-05-31 03:32:00) [23]

Делаешь так:

вызываешь Socket.SendText

он тебе возвращает сколько символов отправлено.

1)Если отправлено столько, сколько передавал - все нормально, идешь дальше.
2) если отправилось меньше - то запоминашь какие символы не отправились и отправляешь их при возниконовении события OnClientWrite


Piter   (2004-05-31 03:29:00) [24]

VID (31.05.04 02:59) [3]
сервером (TServerSocket) автоматически.


TServerSocket? Неблокирующий режим? Хех, что ты фигню городишь?
Зачем тебе спрашивается события OnClientWrite?


VID   (2004-05-31 02:59:00) [25]

Блин, ну неужели я догадался !:)))

решил так:

содрал функцию WaitforData из исходников TWinSocketStream и немного переделал её:

function WaitForData(Socket:TSocket; Timeout: Longint): Boolean;
var
 FDSet: TFDSet;
 TimeVal: TTimeVal;
begin
 TimeVal.tv_sec := Timeout div 1000;
 TimeVal.tv_usec := (Timeout mod 1000) * 1000;
 FD_ZERO(FDSet);
 FD_SET(Socket, FDSet);
 Result := select(0, @FDSet, @FDSet , nil, @TimeVal) > 0;
end;


сразу видно что я переделал :)

а дальше:

for i := 1 to 1000 do
 if waitfordata(socket.sockethandle, 10000) then
   socket.sendtext(s);

и всё...

слава богу, справился :)

PS: Piter, сервер неблокирующий, а Socket это объект типа TCustomWinSocket который создаётся для каждого нового коннекта сервером (TServerSocket) автоматически.


Piter   (2004-05-31 02:36:00) [26]

Что за компонент Socket?


Piter   (2004-05-31 02:36:00) [27]

И какой режим сокетов используется? Блокирующий или не блокирующий?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо