2013-04-01 2 views
1

Я использую протокол UDP Delphi XE2 и Indy10. Я не могу получить серверное эхо на стороне клиента, если я использую метод ReceiveBuffer. Я получил «Socket Error # 10040», хотя я отправляю обратно очень маленькое эхо сообщение от сервера к клиенту. Консольное приложение для иллюстрации моей проблемы приведено ниже. Спасибо заранее.Delphi XE2 Indy10 udp обмен клиент-сервер с использованием SendBuffer-ReceiveBuffer

program Project1; 
{$APPTYPE CONSOLE} 
{$R *.res} 

uses 
    System.SysUtils, IdGlobal, IdBaseComponent, IdComponent, IdSocketHandle, 
    IdUDPClient, IdUDPServer, IdUDPBase, IdStack; 

type 
    TUDP_Serv = class(TIdUDPServer) 
    procedure udpSvUDPRead(AThread: TIdUDPListenerThread; 
     AData: TIdBytes; ABinding: TIdSocketHandle); 
    end; 
var 
    udpServer: TUDP_Serv; 
    udpCl: TIdUDPClient; 
    bSnd, bRcv: TBytes; 
    s: string; 
    k: integer; 
//============================================================================== 
procedure TUDP_Serv.udpSvUDPRead(AThread: TIdUDPListenerThread; AData: TIdBytes; 
    ABinding: TIdSocketHandle); 
begin 
writeln(' Server read: ' + ToHex(AData, length(AData))); 
with ABinding do SendTo(PeerIP, PeerPort, AData); 
end; 
//============================================================================== 
begin 
try 
    udpServer := TUDP_Serv.Create; 
    with udpServer do begin 
    OnUDPRead := udpSvUDPRead; DefaultPort := 20001; BufferSize := 2048; 
    ThreadedEvent := true; Active := True; 
    if Active then writeln('Server started on port: ' + IntToStr(DefaultPort)); 
    end; 
    udpCl := TIdUDPClient.Create; 
    with udpCl do begin 
    BufferSize := 2048; Host := '127.0.0.1'; Port := 20001; 
    end; 
    SetLength(bSnd, 5); bSnd[0] := $31; bSnd[1] := $0; 
    bSnd[2] := $33; bSnd[3] := $0; bSnd[4] := $0; 
    repeat 
    writeln(' Client send: ' + ToHex(bSnd, length(bSnd))); 
    with udpCl do SendBuffer(Host, Port, bSnd); sleep(100); 
    try 
     k := udpCl.ReceiveBuffer(bRcv, 10); 
     if k > 0 then writeln(' Client read: ' + ToHex(bRcv, length(bRcv))); 
    except 
     on E: exception do begin 
     writeln(Format(' Client read err: %s',[E.Message])); 
     end; 
    end; 
    readln(s); 
    until s <> ''; 
except 
    on E: Exception do begin 
    Writeln(E.ClassName, ': ', E.Message); readln(s); 
    end; 
end; 
end. 

экрана:

Server started on prot: 20001 
Client send: 3100330000 
Server read: 3100330000 
Client read err: Socket Error # 10040 
Message too long. 

ответ

0

10040 является WSAEMSGSIZE, что означает, что буфер вы пытались получить в был меньше, чем фактический размер сообщения, которое было получено.

Вы не производите выделение памяти для bRcv перед вызовом ReceiveBuffer(), поэтому вы пытаетесь получить в буфер с 0 байтами, запустите ошибку. Вам необходимо предварительно выделить bRcv, по крайней мере, того же размера, что и ваши сообщения, если не больше.

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

+0

Большое спасибо за объяснение. К сожалению, в Delphi поможет, где нет информации о распределении памяти для этой функции, в то время как ReceiveString «создает временную переменную TIdBytes». –

+0

'bRcv' - динамический массив байтов. Простой 'SetLength()', чтобы выделить его, так же, как вы делаете с 'bSnd'. 'ReceiveString()' использует внутреннюю локальную переменную 'TIdBytes', которая присваивается размеру, указанному свойством' TIdUDPBase.BufferSize', перед вызовом 'ReceiveBuffer()' для заполнения этого 'TIdBytes', тогда содержимое' TIdBytes 'преобразуются в' String'. –

 Смежные вопросы

  • Нет связанных вопросов^_^