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

Вниз

Client/ServerSocket   Найти похожие ветки 

 
Manulo   (2003-10-01 19:49) [0]

Тут такая проблема, в общем вот код
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Host:="10.16.250.60";
ClientSocket1.Open;
ClientSocket1.Socket.SendText("test");
end;


Это со стороны клиента

А это со стороны сервера:

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
begin
Form1.Caption:=Socket.ReceiveText;
end;

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
SpeedButton1.Caption:="connect";
end;


Проблема вот в чём: При нажатии на кнопочку в клиенте (первый кусок) сервер (второй кусок) коннект видит, но не принимает сообщения (то есть не меняется заголовок формочки), а принимает его только при повторном нажатии кнопочки на клиенте (первый кусок). Посоветуйте чё нибудь, а то замучил уже :(


 
Digitman   (2003-10-02 08:22) [1]

Варианты :

1.

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.ClientType := ctBlocking; ClientSocket1.Host:="10.16.250.60";
ClientSocket1.Open;
ClientSocket1.Socket.SendText("test");
end;


2.

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Host:="10.16.250.60";
ClientSocket1.Open;
while not ClientSocket1.Active do
Application.ProcessMessages;

ClientSocket1.Socket.SendText("test");
end;


выбирай на вкус)


 
Manulo   (2003-10-02 18:11) [2]

Digitman © (02.10.03 08:22) [1]
Спасибо, вобщем я уже третим способом разобрался :)


 
Urvin   (2003-10-02 19:35) [3]

У меня та же проблема, какой есть третий способ?


 
Polevi   (2003-10-02 19:47) [4]

SendText в OnWrite


 
Digitman   (2003-10-03 08:19) [5]


> Manulo


> Polevi


для неблок.гнезда см.

> Polevi © (02.10.03 19:47) [4]


лучше и корректней "способа" нет !)


 
Manulo   (2003-10-03 18:43) [6]

щас приведу пример:

procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Host:="10.16.250.60";
ClientSocket1.Open;
end;


procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ClientSocket1.Socket.SendText("test");
end;


В принципе меня устраивает, передача сообщения разовая, после этого просто принимаю ответ и делаю дисконнект.


 
Digitman   (2003-10-04 11:47) [7]

все равно некорректно

это надо делать в OnWrite():

ClientSocket1.Socket.SendText(строка);

кр.того, необходимо анализировать рез-т ф-ции, ибо в условиях глов.сети "строка", если она будет иметь размер более 4кб, не может быть передана за один прием


 
Verg   (2003-10-04 11:58) [8]


> кр.того, необходимо анализировать рез-т ф-ции, ибо в условиях
> глов.сети "строка", если она будет иметь размер более 4кб,
> не может быть передана за один прием


Мм. Не совем так.
Она может быть передана за один прием, хоть 4, хоть 40, хоть 400 кб.
А вот если отправлять кусками, то
SendText(строка1);
SendText(строка2); - вот здесь может возникнуть SOCKET_ERROR+WSAGetLastError=WSAEWOULDBLOCK


 
Digitman   (2003-10-04 13:02) [9]


> Verg



> Она может быть передана за один прием, хоть 4, хоть 40,
> хоть 400 кб.


это только в условиях передачи в пределах лок.машины или лок.сети (и то не следует на это полагаться)

ВСЕГДА следует анализировать результат вызова SendText()
он покажет, был ли помещен фрагмент строки в очередь на передачу, и если помещен, то каков размер этого фрагмента.

т.е. если передаваемая строка имеет длину 10 символов, а метод SendText вернул значение 0 <= N < 10, то это означает : только первые N из 10 символов были успешно поставлены в очередь на передачу, оставшиеся 10 - N символов следует пытаться передать в обработчике ближайшего же возникающего события OnWrite()

если N = -1, то ни один символ передаваемой строки не был поставлен в очередь, схема осуществления повторной попытки - та же

подтверждение - цитата из исходников :

function TCustomWinSocket.SendBuf(var Buf; Count: Integer): Integer;
var
ErrorCode: Integer;
begin
Lock;
try
Result := 0;
if not FConnected then Exit;
Result := send(FSocket, Buf, Count, 0);
if Result = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if (ErrorCode <> WSAEWOULDBLOCK) then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
if ErrorCode <> 0 then
raise ESocketError.CreateResFmt(@sWindowsSocketError,
[SysErrorMessage(ErrorCode), ErrorCode, "send"]);
end;
end;
finally
Unlock;
end;
end;

function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;


 
Digitman   (2003-10-04 13:11) [10]


> вот здесь может возникнуть ...WSAEWOULDBLOCK


как опять же видно из исходников, отказ ф-ции send() с этим кодом ошибки "гасится" прямо на месте, событие OnError() не возбуждается и ф-ция SendText/SendBuf успешно возвращает управление вызвавшему ее коду (который ТУТ ЖЕ должен проанализировать результат вызова !)

по результату, показывающему лишь частичную передачу (либо на отказ передачи при результате -1), следует с полной уверенностью полагаться, что обязательно возникнет OnWrite, в обработчике которого можно произвести повторную попытку передачи еще непереданного фрагмента, с анализом рез-та по той же логике


 
Verg   (2003-10-04 13:27) [11]

Т.е. ты хочешь сказать, что если send завершился без ошибки (-1), то OnWrite все равно возникнет?

Что-то я такого не наблюдал.
Пусть даже send сказал, что взял меньше заказанного числа байт, но надо продолжать его "грузить" остатками буфер, пока он не скажет WSAEWOULDBLOCK. Вот тогда OnWrite гарантирован.

Кстати, посмотри исходник SendStream:
function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer;

procedure DropStream;
begin
if FDropAfterSend then Disconnect(FSocket);
FDropAfterSend := False;
FSendStream.Free;
FSendStream := nil;
end;

begin
Lock;
try
Result := False;
if FSendStream <> nil then
begin
if (FSocket = INVALID_SOCKET) or (not FConnected) then exit;
while True do
begin
StartPos := FSendStream.Position;
try
AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer));
except
ErrorCode := WSAGetLastError;
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end;
if AmountInBuf > 0 then
begin
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else
begin
FSendStream.Position := StartPos;
Break;
end;
end else if AmountInBuf > AmountSent then
FSendStream.Position := StartPos + AmountSent
// чего ж они тут break не сделали? Забыли?
else if FSendStream.Position = FSendStream.Size then
begin
DropStream;
Break;
end;
end else
begin
DropStream;
Break;
end;
end;
Result := True;
end;
finally
Unlock;
end;
end;

function TCustomWinSocket.SendStream(AStream: TStream): Boolean;
begin
Result := False;
if FSendStream = nil then
begin
FSendStream := AStream;
Result := SendStreamPiece;
end;
end;


 
Digitman   (2003-10-04 13:40) [12]


> Verg


да, ты прав , здесь я был не совсем неточен.

"грузить" (если если есть что грузить) следует до тех пор, пока еще остается, что "грузить", либо до получения первого же рез-та = 1. При -1 следует не пыжиться с очередными попытками, а дождаться OnWrite(). Т.е. OnWrite() возникнет по факту первого же полученного "отлупа" с получением -1.


 
Verg   (2003-10-04 13:42) [13]


> Т.е. OnWrite() возникнет по факту первого же полученного
> "отлупа" с получением -1.


Уф. А то я уж подумал, что это у меня "помутнение".... :)

Пиво, однако.... :)



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

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

Наверх





Память: 0.49 MB
Время: 0.004 c
8-11636
Sergo1
2003-08-05 15:56
2003.12.04
Рисование на рисунке.


1-11604
DLLMaN
2003-11-25 15:25
2003.12.04
В бувер из консольной проги.


6-11641
Wiz@rd
2003-10-10 12:41
2003.12.04
Как указать настройки прокси сервера?


8-11625
waw
2003-07-31 14:38
2003.12.04
Как сохранить один кадр фильма в JPEG?


4-11738
AndreyS
2003-10-06 15:46
2003.12.04
Блокировка окна запускаемого консольного приложения





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский