![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Точное определение момента, когда можно отправлять текст в сокет [D5, WinXP]
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]И какой режим сокетов используется? Блокирующий или не блокирующий?