WinSock:服务器未按客户端发送的相同顺序接收数据

布朗

我需要按照确定的顺序客户端服务器发送数据,服务器也可以按客户端发送的相同顺序接收这些数据。在下面的代码中,存在一个问题,即像下一个数据的数据一样接收数据(即控制字节1)。

例如:

客户端上,我有以下几条发送1Connection._Input

if SendInt(Sock, Ord(Connection._Input)) <= 0 then
      Exit;

上面发送的该字节,在Server上正确地在Check变量上接收,而在上接收dwC

看到:

在此处输入图片说明

怎么解决呢?

这是完整的代码:

客户:

program _Client;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Windows,
  WinSock,
  SysUtils;

type
  Connection = (Desktop, _Input);

const
  SendBuf: array [0 .. 9] of AnsiChar = ('A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', #0);

function SendInt(S: TSocket; I: Integer): Integer;
begin
  Result := send(S, I, SizeOf(I), 0);
end;

function ConnectServer: TSocket;
var
  Wsa: WSAData;
  Client: sockaddr_in;
  S: TSocket;
  Rslt: Integer;
begin
  S := INVALID_SOCKET;
  try
    Rslt := WSAStartup(MakeWord(2, 2), Wsa);
    if Rslt = NO_ERROR then
    begin
      S := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
      if S <> INVALID_SOCKET then
      begin
        Client.sin_family := AF_INET;
        Client.sin_addr.s_addr := inet_addr('192.168.15.6');
        Client.sin_port := htons(5099);
        if connect(S, Client, SizeOf(Client)) <> SOCKET_ERROR then
          Writeln('Connected successfully!');
      end;
    end;
  except
    Writeln(SysErrorMessage(WSAGetLastError));
  end;
  Result := S;
end;

function DesktopThread(P: Pointer): DWORD; stdcall;
var
  Sock: TSocket;
  dwC, dwD, dwE, dwF, dwG: DWORD;
  A, B: Integer;
begin
  Result := 0;
  Sock := ConnectServer;

  if send(Sock, SendBuf, SizeOf(SendBuf), 0) <= 0 then
    Exit;

  if SendInt(Sock, Ord(Connection.Desktop)) <= 0 then
    Exit;

  dwC := 111;
  dwD := 222;
  dwE := 333;
  dwF := 444;
  dwG := 555;

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

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

    if SendInt(Sock, Ord(Connection._Input)) <= 0 then
      Exit;

    if SendInt(Sock, dwC) <= 0 then
      Exit;

    if SendInt(Sock, dwD) <= 0 then
      Exit;

    if SendInt(Sock, dwE) <= 0 then
      Exit;

    if SendInt(Sock, dwF) <= 0 then
      Exit;

    if SendInt(Sock, dwG) <= 0 then
      Exit;

    // Writeln(Format('%s', [SysErrorMessage(WSAGetLastError)]));

    Writeln(Format('dwC: %d, dwD: %d, dwE: %d, dwF: %d, dwG: %d',
      [dwC, dwD, dwE, dwF, dwG]));

  until True;
end;

var
  ThrId: Cardinal;

begin
  try
    CreateThread(nil, 0, @DesktopThread, nil, 0, ThrId);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  Readln;

end.

服务器:

program _Server;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  Windows,
  WinSock,
  SysUtils;

type
  Connection = (Desktop, Input, _End);

const
  Buffer: array [0 .. 9] of AnsiChar = ('A', 'B', 'C', 'D', 'E', 'F', 'G',
    'H', 'I', #0);

function SendInt(S: TSocket; I: Integer): Integer;
begin
  Result := send(S, I, SizeOf(I), 0);
end;

function ClientThread(P: Pointer): DWORD; stdcall;
var
  Buf: array [0 .. SizeOf(Buffer) - 1] of AnsiChar;
  Sock: TSocket;
  Check: BOOL;
  A, B: Integer;
  _connection: Connection;
  dwC, dwD, dwE, dwF, dwG: DWORD;
begin
  Result := 0;
  Sock := TSocket(P);

  if recv(Sock, Buf, SizeOf(Buffer), 0) <= 0 then
  begin
    closesocket(Sock);
    Result := 0;
    Exit;
  end;

  if not CompareMem(@Buf, @Buffer, SizeOf(Buffer)) then
  begin
    closesocket(Sock);
    Result := 0;
    Exit;
  end;

  if recv(Sock, _connection, SizeOf(_connection), 0) <= 0 then
  begin
    closesocket(Sock);
    Result := 0;
    Exit;
  end;

  if _connection = Connection.Desktop then
  begin
    A := 666;
    B := 777;
    repeat

      if SendInt(Sock, A) <= 0 then
        Exit;

      if SendInt(Sock, B) <= 0 then
        Exit;

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

      Writeln(BoolToStr(Check));

      { if not Check then
        continue; }

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

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

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

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

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

      // Writeln(Format('%s', [SysErrorMessage(WSAGetLastError)]));

      Writeln(Format('dwC: %d, dwD: %d, dwE: %d, dwF: %d, dwG: %d',
        [dwC, dwD, dwE, dwF, dwG]));

    until True;
  end;
end;

function StartServer(Port: Integer): Boolean;
var
  _wsdata: WSAData;
  serverSocket, S: TSocket;
  _addrIn, _addr: sockaddr_in;
  addrSize: Integer;
  tid: Cardinal;
begin
  Result := False;

  if WSAStartup(MakeWord(2, 2), _wsdata) <> 0 then
    Exit;

  serverSocket := socket(AF_INET, SOCK_STREAM, 0);

  if serverSocket = INVALID_SOCKET then
    Exit;

  _addrIn.sin_family := AF_INET;
  _addrIn.sin_addr.S_addr := INADDR_ANY;
  _addrIn.sin_port := htons(Port);

  if bind(serverSocket, _addrIn, SizeOf(_addrIn)) = SOCKET_ERROR then
    Exit;

  if listen(serverSocket, SOMAXCONN) = SOCKET_ERROR then
    Exit;

  addrSize := SizeOf(_addrIn);
  getsockname(serverSocket, _addrIn, addrSize);

  Writeln(Format('Listening on port %d.' + #13, [ntohs(_addrIn.sin_port)]));

  while True do
  begin
    S := accept(serverSocket, @_addr, @addrSize);
    CreateThread(nil, 0, @ClientThread, Pointer(S), 0, tid);
  end;

  Result := True;
end;

begin
  try
    if not StartServer(5099) then
      Writeln(SysErrorMessage(WSAGetLastError));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;

end.
汤姆·布朗伯格

客户端与服务器的数据大小不一致。

type
  Connection = (Desktop, _Input);

Delphi中枚举的默认大小为byte这本身是可以的,但是您在客户端和服务器中对它们的处理方式不同。

您可以使用SendInt()转换为整数的函数从客户端发送消息

在服务器端,您收到的SizeOf(_connection)只是一个字节。由于字节顺序,1其余部分保留在缓冲区中,以后再读入dwC

您可以通过将Minimum enum size项目选项设置doubleword或作为字节发送来更正错误


评论后编辑

确实,您还存在另一个错误或误解。

从您发送的客户

SendInt(Sock, Ord(Connection._Input))

服务器收到的是

var
  Check: BOOL;
....
  recv(Sock, Check, SizeOf(Check), 0) , 

然后你写成

Writeln(BoolToStr(Check)); 

并且控制台显示“ -1”。但这不是错误,已记录在案:

System.SysUtils.BoolToStr

Value of B  Value of UseBoolStrs  Value of returned string  
  true        false                 '-1' 

也许您想将其显示为枚举值。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++服务器无法从客户端/ Winsock接收数据

服务器无法在c winsock编程中接收到客户端消息

从客户端向服务器发送大量数据

客户端不向服务器发送数据

客户端如何获取发送到服务器的请求的完成状态通知?-Winsock

C ++客户端无法发送到服务器/ Winsock

如何使用Node.js在服务器上接收与客户端发布数据格式相同的发布数据?

Winsock 客户端和服务器无法连接

(Socket.SendTo)如何响应/将数据发送回服务器开始接收的客户端?C#

服务器端排序的数据在数据表中未按相同顺序显示

从本地客户端计算机向Ubuntu服务器上的Flask服务器发送和接收数据

套接字IO客户端从服务器发送的内容中接收对象不同

套接字服务器无法接收客户端发送的消息

无法在客户端发送的服务器中接收文件名

客户端while循环从服务器发送和接收

解析推送通知是从服务器发送的,但客户端未接收到

Java多线程套接字客户端/服务器:发送和接收Enummap对象

为什么我的Android客户端无法从Winsock C ++服务器接收字符串消息?

客户端/服务器聊天,发送在线用户列表,仅由最近连接的客户端接收?

测量udp服务器发送的数据与客户端接收的数据之间的延迟

接收服务器对客户端请求的响应

如何将客户端数据发送到服务器端

无法从Java套接字服务器接收数据到C套接字客户端

跨NAT的UDP客户端无法从服务器接收数据

如何从Java SUB客户端(ZMQ)上的Python ZeroMQ PUB服务器接收数据

从服务器C#接收数据到客户端delphi

客户端没有从服务器python接收数据

Python套接字服务器-继续接收客户端数据

奇怪的是,服务器接收到的数据比我从客户端获得的更多