Форум: "Сети";
Текущий архив: 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