Как правильно отправить / получить целочисленное значение, используя встроенный winsock в одну строку, аналогично приведенному ниже коду C ++? Я пытался перевести это, но не знаю, если это правильно. Может кто-то мне помочь, пожалуйста?

C ++:

enum MyEnum { element01, element02 };
int width;

int SendInt(SOCKET sock, int i)
{
   return Send(sock, (char *) &i, sizeof(i), 0);
}

if(SendInt(sock, MyEnum::element01) <= 0) return;
if(SendInt(sock, 0) <= 0) return;
if(recv(sock, (char *) &width, sizeof(width), 0) <= 0) return;

Delphi :

type
  MyEnum = (element01, element02);

var
 Width: Integer;

function SendInt(S: TSocket; I: Integer): Integer;
begin
  Result := send(S, PAnsiChar(I)^, Length(IntToStr(I)), 0);
end;

if SendInt(Sock, Integer(MyEnum.element01)) <= 0 then Exit;
if SendInt(Sock, 0) <= 0 then Exit;
if recv(Sock, PAnsiChar(Width)^, Length(IntToStr(Width)), 0) <= 0 then Exit;
-1
BrowJr 16 Апр 2019 в 01:04

2 ответа

Лучший ответ

Ты используешь:

function SendInt(S: TSocket; I: Integer): Integer;
begin
  Result := send(S, PAnsiChar(I)^, Length(IntToStr(I)), 0);
end;

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

Вы можете просто сделать это:

begin
  Result := send(S, I, SizeOf(I), 0);
end;

Хотя вам, возможно, придется изменить порядок байтов с помощью htonl () :

begin
  // I := htonl(I); ??
  Result := send(S, I, SizeOf(I), 0);
end;

Вы должны попробовать обе альтернативы и посмотреть, что из этого получится. Один из них правильный.

Вы также должны передать целое число таким же образом, используя recv () . Возможно, вам придется использовать ntohl () (противоположность htonl () ) после вызова recv () :

function RecvInt(S: TSocket; var J: Integer): Integer;
begin
  Result := recv(S, J, SizeOf(J), 0);
  // J := ntohl(J); ??
end;
2
Rudy Velthuis 16 Апр 2019 в 06:14

Вызов send неправильный. Вы должны предоставить нетипизированный буфер для байтов, которые должны быть отправлены, и количество байтов. Абсолютно нет места для IntToStr здесь.

Result := send(S, I, SizeOf(I), 0);

И аналогично для вызова recv.

if recv(Sock, Width, SizeOf(Width), 0) <= 0 then Exit;

Идиоматично использовать Ord() для получения порядкового значения перечислимого типа Delphi, поэтому Ord(MyEnum.element01), а не Integer(MyEnum.element01), но конечный результат будет точно таким же.

Ваш код не конвертируется между порядком байтов хоста и сети. Но тогда, также как и код C ++.

2
David Heffernan 15 Апр 2019 в 22:34