Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.06.16;
Скачать: [xml.tar.bz2];

Вниз

Несколько вопросов по блокирующим сокетам   Найти похожие ветки 

 
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; - приват-поле формы.

Логика клиента – в procedure TISClientThread.Execute в первом сообщении.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2003.06.16;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.007 c
14-50471
Мазут Береговой Рюрикович
2003-05-30 10:09
2003.06.16
Не могу не поделиться....


8-50408
spijon
2003-03-04 21:33
2003.06.16
Програмно нарисовать текст


14-50474
Move
2003-05-28 12:42
2003.06.16
сервер базы данных


1-50279
iNew
2003-06-04 14:50
2003.06.16
Вопрос по потокам.


3-50238
Ann
2003-05-26 16:15
2003.06.16
ComboBox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский