gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 18:39:55 25 4
gpt4 key购买 nike

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

前任:

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

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

上面发送的这个字节,在 服务器上,正确的是在 Check变量上接收的,而在 dwC上接收的。

看:

enter image description here

怎么解决呢?

这是完整的代码:

客户:
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'

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

关于sockets - WinSock:服务器未按客户端发送的相同顺序接收数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55896318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com