Текущий архив: 2003.06.16;
Скачать: CL | DM;
ВнизНесколько вопросов по блокирующим сокетам Найти похожие ветки
← →
Akni (2003-04-09 22:08) [0]Добрый вечер, Мастера!
Пишу клиент-серверное приложение, используя TclientSocket, TserverSocket компоненты в блокирующем режиме.
Идея такова:
- сервер посылает клиенту Record с определенной периодичностью;
- клиент может иногда посылать серверу одноразовое сообщение;
- передача файлов в обе стороны.
Вопросы:
1. Какой смысл параметра TimeOut в конструкторе WinSocketStream.Create? Только не надо меня сразу отсылать в help, я там уже была.
Проблема такая: если я создаю серверный поток с Timeout N секунд, а Record от сервера дожен отправляться каждые K секунд, K<N, то данные отправляются только раз в N секунд, т.е. тело цикла
while (not Terminated) and ClientSocket.Connected do ...
выполняется раз в N секунд
2. Когда клиент и сервер работают на одном компе, то весь обмен данными происходит мгновенно. Когда на разных, то выглядит все примерно так:
на сервере возникает событие OnAccept сразу после того, как клиент посылает запрос, а первая порция данных от сервера приходит только через 30-40 сек. С чем это связано?
3. Является ли «идеологически правильным» подходом такой прием-передача файлов, как в нижеприведенном коде?
Заранее всем спасибо.
Ниже приблизительный код.
сервер:
procedure TISServerThread.ClientExecute;
var Stream: TWinSocketStream;
SizeOfBuffer: integer;
iRecvdCode: integer;
fStream: TFileStream;
Size1: longint;
pBuffer: pointer;
Buffer: array[0..BufSize] of Byte;
begin
inherited FreeOnTerminate:=true;
fRecSend:=true;
try
Stream:=TWinSocketStream.Create(ClientSocket, 500);
try
while (not Terminated) and ClientSocket.Connected do
begin
if fRecSend then
begin
iCode:=cdRec;
Stream.Write(iCode, sizeOf(iCode));
Stream.Write(GlobalDat, SizeOF(GlobalDat));
end;
if Stream.WaitForData(1000) then
begin
SizeOfBuffer:=Stream.Read(iRecvdCode,sizeOf(iRecvdCode));
if SizeOfBuffer>0 then
begin
case iRecvdCode of
...
cdFILE_TOSERVER:
begin
SetLength(fSource,255);
Size1:=Stream.Read(fSource[1],255);
setLength(fSource,size1);
Stream.Read(Size1, SizeOf(Size1));
fStream:=TFileStream.Create(fSource,fmCreate or fmOpenWrite);
repeat
pbuffer:=@buffer;
Size1:=Stream.Read(pBuffer^,BufSize);
fStream.Write(pBuffer^, size1);
until Size1=0;
fStream.Free;
end;
end;
end;
end;
end;
finally
Stream.Free;
end;
except
on E: Exception do
begin
ClientSocket.Close;
Terminate;
end;
end;
end;
клиент:
procedure TISClientThread.Execute;
var Stream: TWinSocketStream;
SizeOfBuffer: integer;
Size1: longint;
iREcvdCode: integer;
fStream: TFileStream;
begin
try
fClientSocket:=TClientSocket.Create(nil);
try
fClientSocket.Address := ServerAddress;
fClientSocket.Port := ServerPort;
fClientSocket.ClientType := ctBlocking;
Stream := TWinSocketStream.Create(fClientSocket.Socket, iTimeOut);
fClientSocket.Active := True;
if fClientSocket.Active then
begin
iCode:=cdOK;
Stream.Write(iCode, sizeof(iCode));
end;
while (not Terminated) and (fClientSocket.Active) do
begin
case fActionCode of
...
cdFILE_TOSERVER:
begin
iCode:=fActionCode;
Stream.Write(iCode, SizeOf(iCode));
fActionCode:=0;
Stream.Write(Pointer(fDestination)^,Length(fDestination)); //имя файла
fStream:=TFileStream.Create(fSource, fmOpenRead or fmShareDenyNone);
Size1:=fStream.size;
Stream.Write(Size1,sizeof(size1)); //размер файла
SizeOfBuffer:=Stream.CopyFrom(fStream,0); //сам файл
fStream.Free;
end;
end;
if Stream.WaitForData(1000) then
begin
if (not Terminated) and (fClientSocket.Active) then
begin
SizeOfBuffer:=Stream.Read(iRecvdCode, sizeOf(iRecvdCode));
if SizeOfBuffer>0
then
case iRecvdCode of
cdREC:
Stream.Read(GlobalRcvdDat,sizeOf(GlobalRcvdDat));
end;
end
end
end;
finally
fClientSocket.Active := False;
fClientSocket.Free;
Stream.Free;
end;
except
on E: Exception do
begin
fClientSocket.Close;
Terminate;
end;
end;
end;
← →
Digitman (2003-04-10 09:04) [1]
> 1. Какой смысл параметра TimeOut в конструкторе WinSocketStream.Create?
> Только не надо меня сразу отсылать в help, я там уже была.
И что непонятно там, в хэлпе ?
> Проблема такая: если я создаю серверный поток с Timeout
> N секунд, а Record от сервера дожен отправляться каждые
> K секунд, K<N, то данные отправляются только раз в N секунд
Делай K на порядок-другой больше чем N - и нет проблемы !
Можно в кач-ве тайм-аута использовать и спец.константу INFINITE, которая означает бесконечное ожидание.
> 2. Когда клиент и сервер работают на одном компе, то весь
> обмен данными происходит мгновенно.
В этом нет ничего удивительного - работает т.н. loopback
> Когда на разных, то выглядит все примерно так:
> на сервере возникает событие OnAccept сразу после того,
> как клиент посылает запрос, а первая порция данных от сервера
> приходит только через 30-40 сек. С чем это связано?
если сервер в ответ на событие OnClientConnect/OnAccept пытается получить св-во RemoteHost вновь подключившегося клиента, то немаловероятно, что такая задержка м.б. связана и с отсутствием/некорректностью работы службы DNS, задача которой в дан.случае - разрешение IP-адреса в имя хоста
> 3. Является ли «идеологически правильным» подходом такой
> прием-передача файлов, как в нижеприведенном коде?
В общем и целом реализованная логика идеологически не вызывает каких-либо серьезных противоречий, но - достаточно много некорректностей и "недосмотров" по обработке некоторых потенциально возникающих (в условиях глоб.сети) ситуаций.
← →
Digitman (2003-04-10 09:09) [2]
> 1. Какой смысл параметра TimeOut в конструкторе WinSocketStream.Create?
> Только не надо меня сразу отсылать в help, я там уже была.
И что непонятно там, в хэлпе ? тайм-аут - время по-умолчанию, в теч.которого транп.методы Read/Write будут "ждать" успешного приема/отправки хотя бы части запрошенных к приему/передаче данных, и по истечении которого (в случае неуспеха) операция будет отменена и будет сгенерирована искл.ситуация ESocketError
> Проблема такая: если я создаю серверный поток с Timeout
> N секунд, а Record от сервера дожен отправляться каждые
> K секунд, K<N, то данные отправляются только раз в N секунд
Делай K на порядок-другой больше чем N - и нет проблемы !
Можно в кач-ве тайм-аута использовать и спец.константу INFINITE, которая означает бесконечное ожидание.
> 2. Когда клиент и сервер работают на одном компе, то весь
> обмен данными происходит мгновенно.
В этом нет ничего удивительного - работает т.н. loopback
> Когда на разных, то выглядит все примерно так:
> на сервере возникает событие OnAccept сразу после того,
> как клиент посылает запрос, а первая порция данных от сервера
> приходит только через 30-40 сек. С чем это связано?
если сервер в ответ на событие OnClientConnect/OnAccept пытается получить св-во RemoteHost вновь подключившегося клиента, то немаловероятно, что такая задержка м.б. связана и с отсутствием/некорректностью работы службы DNS, задача которой в дан.случае - разрешение IP-адреса в имя хоста
> 3. Является ли «идеологически правильным» подходом такой
> прием-передача файлов, как в нижеприведенном коде?
В общем и целом реализованная логика идеологически не вызывает каких-либо серьезных противоречий, но - достаточно много некорректностей и "недосмотров" по обработке некоторых потенциально возникающих (в условиях глоб.сети) ситуаций.
← →
Akni (2003-04-10 18:03) [3]то немаловероятно, что такая задержка м.б. связана и с отсутствием/некорректностью работы службы DNS, задача которой в дан.случае - разрешение IP-адреса в имя хоста
v tom-to i delo, chto ja ukazivaju IP-Adres, a ne Host
tochnee vigljadit eto tak:
1. Client pitaetsja spjedinitsja s serverom
2. Cherez priblizit. 20 sek na Servere protokollieruetsja OnAccept
3. esche cherez pribl. 15-20 sek na Servere nachinaet vipolnjatsja ServerThread.ClientExecute
4. Srazu posle etogo Client poluchaet otvet ot Servera
но - достаточно много некорректностей и "недосмотров" по обработке некоторых потенциально возникающих (в условиях глоб.сети) ситуаций.
A mozhno popodrobnee, kakie nedorabotki; a to u menja etot kod tol"ko v predelach odnogo kompa rabotaet
P.S. Sorry za translit, net na firme russkich fontov
← →
Digitman (2003-04-11 08:37) [4]
> 2. Cherez priblizit. 20 sek na Servere protokollieruetsja
> OnAccept
если именно IP-адрес используется (а не Host), то это оч похоже на некорректную настройку шлюзов и маршрутизации на клиентской машине.
опиши конфигурацию своей подсети и настройки TCP-протокола на машинах сервера и клиента
> 3. esche cherez pribl. 15-20 sek na Servere nachinaet vipolnjatsja
> ServerThread.ClientExecute
после OnAccept() ??? через 15-20 сек. ??? не верю !! Быть того не может !!
ServerClientThread стартует немедленно сразу за OnAccept + OnClientConnect. Даже если поток взят не из кэша, по время создания и старта нового потока (OnGetThread) - дело максимум десятых долей секунды.
приведи код кл.стороны, осуществляющий коннект с сервером
← →
Akni (2003-04-11 15:29) [5]похоже на некорректную настройку шлюзов и маршрутизации на клиентской машине.
Похоже на то. Как только взяла другой комп. в качестве сервера, все заработало. Вот только странно, что все остальные обращения к «проблемному» серверу (ping, напр.) происходят мгновенно
приведи код кл.стороны, осуществляющий коннект с сервером
Клиент создается так:
procedure TfrmMonitoring.StartThread;
begin
ClThread:=TISClientThread.Create(SElf);
ClThread.Log:=fLog;
ClThread.ServerAddress:=ServerAddress;
ClThread.ServerPort:=ServerPort;
ClThread.FormHandle:=Handle;
ClThread.Resume;
end;
ClThread: TISClientThread;
- приват-поле формы.
Логика клиента – в procedureTISClientThread.Execute
в первом сообщении.
Страницы: 1 вся ветка
Текущий архив: 2003.06.16;
Скачать: CL | DM;
Память: 0.48 MB
Время: 0.005 c