Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets WinSock:服务器未按客户端发送的相同顺序接收数据_Sockets_Delphi_Winsock_Delphi 10 Seattle_Recv - Fatal编程技术网

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

Sockets WinSock:服务器未按客户端发送的相同顺序接收数据,sockets,delphi,winsock,delphi-10-seattle,recv,Sockets,Delphi,Winsock,Delphi 10 Seattle,Recv,我需要以确定的顺序将数据从客户端发送到服务器,服务器也可以按照客户端发送的相同顺序接收这些数据。在下面的代码中存在一个问题,即接收到的数据(即控制字节,1)与接收下一个数据的数据一样 例: 在客户机上我有以下一段发送1(连接。_Input) 服务器: program _Server; {$APPTYPE CONSOLE} {$R *.res} uses Windows, WinSock, SysUtils; type Connection = (Desktop, Input

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

例:

客户机上我有以下一段发送1
连接。_Input

服务器:

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.
program\u服务器;
{$APPTYPE控制台}
{$R*.res}
使用
窗户,
温索克,
SysUtils;
类型
连接=(桌面,输入,_端);
常数
缓冲区:AnsiChar=('A','B','C','D','E','F','G',的数组[0..9],
‘H’、‘I’、#0);
函数SendInt(S:TSocket;I:Integer):整数;
开始
结果:=send(S,I,SizeOf(I),0);
结束;
函数ClientThread(P:指针):DWORD;stdcall;
变量
Buf:AnsiChar的数组[0..SizeOf(Buffer)-1];
短袜:短袜;
检查:布尔;
A、 B:整数;
_连接:连接;
dwC、dwD、dwE、dwF、dwG:DWORD;
开始
结果:=0;
短袜:=短袜(P);

如果recv(Sock,Buf,SizeOf(Buffer),0)则客户端与服务器中的数据大小不一致

type
  Connection = (Desktop, _Input);
Delphi中枚举的默认大小为
字节
。这本身是可以的,但在客户端和服务器中处理这些问题的方式不同

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

在服务器端,您以
SizeOf(\u connection)
的形式接收它,它只是一个字节。由于字节顺序的原因,
1
保留在缓冲区中,随后被读入
dwC

您可以通过将项目选项中的
最小枚举大小
设置为
双字
或以字节形式发送来更正错误


评论后编辑

事实上,你还有另一个错误,或者可能是误解

从您发送的客户端

SendInt(Sock, Ord(Connection._Input))
由服务器接收为

var
  Check: BOOL;
....
  recv(Sock, Check, SizeOf(Check), 0) , 
然后你把它写成

Writeln(BoolToStr(Check)); 
控制台显示“-1”。但这不是一个错误,有文件记录:


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

谢谢您的回答,但这些建议并非100%有效。我收到的是-1而不是1。“
通过将项目选项中的最小枚举大小设置为doubleword
”有效。然后,这个问题中的问题似乎是IDE,因为我在VC++中用VS2013编译了类似的代码,这是不可能的。我不确定我是否理解了C++代码和VS2013的引用。但是,如果这个问题现在得到了回答,你知道该怎么办;-)
var
  Check: BOOL;
....
  recv(Sock, Check, SizeOf(Check), 0) , 
Writeln(BoolToStr(Check)); 
Value of B  Value of UseBoolStrs  Value of returned string  
  true        false                 '-1'