2016-02-21 2 views
2

Я использую delphi (RAD Studio 10), чтобы сделать небольшой клиент и сервер приложений. Сервер отправляет только текст.Функция recv не принимает все байты

Следующие функции правильно возвращают количество отправленных байтов. Например, я отправить 'привет' (на стороне клиента):

procedure TTCPConnection.Write(S: String); 
var buff : string; 
begin 
    buff = S+EOL; 
    WriteBuffer(buff, Length(buff)); 
end; 

Где: S = 'hello' и EOL = #13#10, так buff = 'hello'+EOL.

procedure TTCPConnection.WriteBuffer(var Buffer; const Len: Cardinal); 
var 
    a : Int16; 
begin 
    a := send(FSocket, Buffer, Len, 0); 
    if (a = SOCKET_ERROR) and FConnected then 
    begin 
    HandleError; 
    Disconnect; 
    end; 
end; 

в предыдущей функции: send(FSocket, Buffer, Len, 0) возвращение 7, количество отправленных байт ('привет + EOL').

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

function TTCPConnection.ReadLn(Delim: String = EOL): String; 
const BUFFER_SIZE = 255; 
var 
    Buff, Buf: string; 
    I, L: Cardinal; 
begin 
    Result := ''; 
    I := 1; 
    L := 1; 
    SetLength(Buff, BUFFER_SIZE); 
    Buf := AnsiString(Buff); 
    while Connected and (L <= Cardinal(Length(Delim))) do 
    begin 
    if recv(FSocket, Buffer, Len, 0) < 1 then exit; 
    Buf := Buff[I]; 
    if Buff[I] = Delim[L] then 
     ... 
    ... 
end; 

(В предыдущем коде я включаю Buf вар для целей отладчика только). Когда я отлаживаю полученный результат:

Buff = {'h', #0, 'e', #0, 'l', #0, 'l'} (7 байт), а в следующий раз, когда эта строка выполнена, программа ничего не делает, я думаю, это потому, что функция recv ничего не получает (отправлено 7 байт).

Мне нужна помощь, чтобы все байты были получены правильно. Я не знаю, почему они в этом порядке (h-#0-e-#0-l-#0-l).

ответ

0

Начиная с RAD Studio 2009, string состоит из WideChar символов. Char - это псевдоним для WideChar и 16 бит. Функция Length() возвращает количество символов, а не байтов.

Возможно, вы захотите использовать TEncoding для преобразования строки в TBytes (array of byte) для отправки и для получения. Я не знаю ваш TTCPConnection класса, так что это может быть вам нужно Твик код, но здесь для отправки части, используя TEncoding.UTF8:

procedure TTCPConnection.Write(S: String); 
var buff : TBytes; 
begin 
    buff := TEncoding.UTF8.GetBytes(S+EOL); // Convert to bytes using UTF8 encoding 
    WriteBuffer(buff, Length(buff)); 
end; 

А вот мой код приемника из TestProject в xe5, где я в TTcpServer компонент

procedure TForm3.TcpServer1Accept(Sender: TObject; 
    ClientSocket: TCustomIpClient); 
var 
    a: array[0..255] of byte; 
    b: TBytes; 
    i, n: integer; 
    s: string; 
begin 
    n := ClientSocket.ReceiveBuf(a,255,0); 
    SetLength(b, n); 
    for i := Low(b) to High(b) do b[i] := a[i]; // copy from the receive buffer 
    s := TEncoding.UTF8.GetString(b);   // convert UTF8 bytes to string 
    Memo1.Lines.Add(format('%4d %s',[n,s])); 
end; 

Наконец несколько полезных ссылок на документацию:

TEncoding

UTF-8 Conversion Routines

+0

Спасибо. теперь функция recv получает полную информацию 'Buff = {'h', # 0, 'e', ​​# 0, 'l', # 0, 'l', # 0, 'o', '$ D', # 0, '$ A'} '. Теперь, я должен построить новый буфер без' # 0'? или я делаю что-то неправильно, что не показано так, как должно быть? ('Buff = {'h', 'e', ​​'l', 'l', 'o', '$ D', '$ A'}') – Jota69

+0

@Tom Ни один из ваших вариантов не является хорошим. С UTF16 вам нужно заняться контентом. Если вы хотите избежать использования 8-разрядной кодировки Unicode, UTF8. –

+0

@ Jota69 Вам нужно прекратить отправку текста и начать думать о кодировании текста как двоичного кода в определенной кодировке. UTF8 - лучший выбор. –

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