阿
阿伟~
Unregistered / Unconfirmed
GUEST, unregistred user!
如题,写了个小DEMO,但在服务端处理数据的时候却出现了问题收到的全是乱码,废话不多说先看代码,相关地方都有标注,服务器端完整代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, WinSock2, StdCtrls;
const
DATA_BUFSIZE = 6; //接收缓冲区大小
type
TServer = class(TThread)
private
dwEventTotal: DWORD; // 程序中事件的总数初始化时为0
dwRecvBytes: DWORD; // 接收到的字符长度
Flags: DWORD; // WSARecv的参数
DataBuf: array[0..DATA_BUFSIZE - 1] of WSABUF; //WSARECV里的缓冲区参数
buffer: array[0..DATA_BUFSIZE - 1] of Char;
AcceptOverlapped: WSAOVERLAPPED; // 重叠结构
EventArray: array[0..WSA_MAXIMUM_WAIT_EVENTS - 1] of WSAEVENT; // 用来通知重叠操作完成的事件句柄数组
{ Private declarations }
protected
constructor Create(CreateSuspended: Boolean);
procedure Execute; override;
procedure InitOverLapped;
procedure Initbl;
procedure OperSock;
end;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
function InitSock: Boolean;
procedure ShowStatus(s: string);
function InitSockAddrIn(IP: string; Port: word): TSockAddrIn;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
ListenSocket: TSocket; // 监听套接字
AcceptSocket: TSocket; // 与客户端通信的套接字
function TForm1.InitSock: Boolean;
var
wsaData: TWSAData;
SockAddrIn: TSockAddrIn;
begin
Result := True;
if WSAStartup(MAKEWORD(2, 2), wsaData) <> 0 then
begin
ShowStatus('初始化Winsock2失败');
Result := False;
Exit;
end
else
ShowStatus('初始化Winsock2_dll成功');
ListenSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建TCP套接字
if ListenSocket = INVALID_SOCKET then
begin
ShowStatus('创建监听套接字失败');
Result := False;
Exit;
end
else
begin
ShowStatus('创建监听套接字成功');
SockAddrIn := InitSockAddrIn('', 8090);
if bind(ListenSocket, @SockAddrIn, sizeof(SockAddrIn)) < 0 then
begin
CloseSocket(ListenSocket);
ShowStatus('绑定服务地址失败');
Result := False;
Exit;
end
else
ShowStatus('绑定服务地址成功');
end;
listen(ListenSocket, 5); //开始监听
end;
function TForm1.InitSockAddrIn(IP: string; Port: word): TSockAddrIn;
begin
Result.sin_family := PF_INET;
if IP <> '' then
Result.sin_addr.s_addr := inet_addr(pchar(IP))
else
Result.sin_addr.s_addr := INADDR_ANY;
Result.sin_port := htons(Port);
end;
procedure TForm1.ShowStatus(s: string);
begin
memo1.Lines.Add(s);
memo1.Lines.Add(' ');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
a: TServer;
begin
if not InitSock then //初始化服务端套接字
Abort;
a := TServer.Create(False);
end;
constructor TServer.Create(CreateSuspended: Boolean);
begin
Initbl; //初始化成员变量
InitOverLapped; //初始化OVERLapped结构
inherited Create(CreateSuspended);
end;
procedure TServer.Execute;
var
ClientAddr: SOCKADDR_IN;
addr_len: integer;
IP: PChar;
Port: DWORD;
s: string;
begin
while not Terminated do
begin
addr_len := SizeOf(ClientAddr);
AcceptSocket := accept(ListenSocket, ClientAddr, addr_len);
IP := inet_ntoa(ClientAddr.sin_addr);
Port := ClientAddr.sin_port;
s := '接收到来自IP:' + IP + ' ' + 'PORT:' + IntToStr(Port) + ' 的一个连接';
form1.ShowStatus(s);
OperSock;
end;
end;
procedure TServer.Initbl;
begin
dwEventTotal := 0;
dwRecvBytes := 0;
Flags := 0;
end;
procedure TServer.InitOverLapped;
var
i: integer;
begin
EventArray[dwEventTotal] := WSACreateEvent();
ZeroMemory(@AcceptOverlapped, SizeOf(AcceptOverlapped));
AcceptOverlapped.hEvent := EventArray[dwEventTotal];
ZeroMemory(@buffer, DATA_BUFSIZE);
for i := 0 to DATA_BUFSIZE - 1 do
begin
DataBuf.len := DATA_BUFSIZE;
DataBuf.buf := buffer;
end;
Inc(dwEventTotal);
end;
procedure TServer.OperSock;
var
dwIndex, dwBytesTransferred: DWORD;
s: string;
i: integer;
begin
if WSARecv(AcceptSocket, @DataBuf, 1, dwRecvBytes, Flags, @AcceptOverlapped, nil) = SOCKET_ERROR then
if (WSAGetLastError <> WSA_IO_PENDING) then // 返回WSA_IO_PENDING是正常情况,表示IO操作正在进行,不能立即完成
begin
CloseSocket(AcceptSocket);
WSACloseEvent(EventArray[dwEventTotal]);
Exit;
end;
dwIndex := WSAWaitForMultipleEvents(dwEventTotal, @EventArray, FALSE, WSA_INFINITE, FALSE);
dwIndex := dwIndex - WSA_WAIT_EVENT_0;
WSAResetEvent(EventArray[dwIndex]);
WSAGetOverlappedResult(AcceptSocket, @AcceptOverlapped, @dwBytesTransferred, FALSE, Flags);
if dwBytesTransferred = 0 then //传输的字节数,如果为0表示对方套接字已经关闭
begin
CloseSocket(AcceptSocket);
WSACloseEvent(EventArray[dwIndex]); // 关闭事件
Exit;
end;
for i := 0 to DATA_BUFSIZE - 1 do //此处从缓冲区中取出的数据全是乱码,但收到的字节数是对的也就是dwBytesTransferred的对的
if Trim(s) = '' then
s := DataBuf.buf
else
s := s + DataBuf.buf;
form1.ShowStatus(s);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(AcceptSocket);
end;
end.
******************************************************************************
客户端就简单了,就不列代码了主要就一句:
s := 'hello';
Send(CltSock, s, Length(s), 0);
哪位大虾能帮我看看服务端的问题到底出在哪?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, WinSock2, StdCtrls;
const
DATA_BUFSIZE = 6; //接收缓冲区大小
type
TServer = class(TThread)
private
dwEventTotal: DWORD; // 程序中事件的总数初始化时为0
dwRecvBytes: DWORD; // 接收到的字符长度
Flags: DWORD; // WSARecv的参数
DataBuf: array[0..DATA_BUFSIZE - 1] of WSABUF; //WSARECV里的缓冲区参数
buffer: array[0..DATA_BUFSIZE - 1] of Char;
AcceptOverlapped: WSAOVERLAPPED; // 重叠结构
EventArray: array[0..WSA_MAXIMUM_WAIT_EVENTS - 1] of WSAEVENT; // 用来通知重叠操作完成的事件句柄数组
{ Private declarations }
protected
constructor Create(CreateSuspended: Boolean);
procedure Execute; override;
procedure InitOverLapped;
procedure Initbl;
procedure OperSock;
end;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
function InitSock: Boolean;
procedure ShowStatus(s: string);
function InitSockAddrIn(IP: string; Port: word): TSockAddrIn;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
ListenSocket: TSocket; // 监听套接字
AcceptSocket: TSocket; // 与客户端通信的套接字
function TForm1.InitSock: Boolean;
var
wsaData: TWSAData;
SockAddrIn: TSockAddrIn;
begin
Result := True;
if WSAStartup(MAKEWORD(2, 2), wsaData) <> 0 then
begin
ShowStatus('初始化Winsock2失败');
Result := False;
Exit;
end
else
ShowStatus('初始化Winsock2_dll成功');
ListenSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建TCP套接字
if ListenSocket = INVALID_SOCKET then
begin
ShowStatus('创建监听套接字失败');
Result := False;
Exit;
end
else
begin
ShowStatus('创建监听套接字成功');
SockAddrIn := InitSockAddrIn('', 8090);
if bind(ListenSocket, @SockAddrIn, sizeof(SockAddrIn)) < 0 then
begin
CloseSocket(ListenSocket);
ShowStatus('绑定服务地址失败');
Result := False;
Exit;
end
else
ShowStatus('绑定服务地址成功');
end;
listen(ListenSocket, 5); //开始监听
end;
function TForm1.InitSockAddrIn(IP: string; Port: word): TSockAddrIn;
begin
Result.sin_family := PF_INET;
if IP <> '' then
Result.sin_addr.s_addr := inet_addr(pchar(IP))
else
Result.sin_addr.s_addr := INADDR_ANY;
Result.sin_port := htons(Port);
end;
procedure TForm1.ShowStatus(s: string);
begin
memo1.Lines.Add(s);
memo1.Lines.Add(' ');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
a: TServer;
begin
if not InitSock then //初始化服务端套接字
Abort;
a := TServer.Create(False);
end;
constructor TServer.Create(CreateSuspended: Boolean);
begin
Initbl; //初始化成员变量
InitOverLapped; //初始化OVERLapped结构
inherited Create(CreateSuspended);
end;
procedure TServer.Execute;
var
ClientAddr: SOCKADDR_IN;
addr_len: integer;
IP: PChar;
Port: DWORD;
s: string;
begin
while not Terminated do
begin
addr_len := SizeOf(ClientAddr);
AcceptSocket := accept(ListenSocket, ClientAddr, addr_len);
IP := inet_ntoa(ClientAddr.sin_addr);
Port := ClientAddr.sin_port;
s := '接收到来自IP:' + IP + ' ' + 'PORT:' + IntToStr(Port) + ' 的一个连接';
form1.ShowStatus(s);
OperSock;
end;
end;
procedure TServer.Initbl;
begin
dwEventTotal := 0;
dwRecvBytes := 0;
Flags := 0;
end;
procedure TServer.InitOverLapped;
var
i: integer;
begin
EventArray[dwEventTotal] := WSACreateEvent();
ZeroMemory(@AcceptOverlapped, SizeOf(AcceptOverlapped));
AcceptOverlapped.hEvent := EventArray[dwEventTotal];
ZeroMemory(@buffer, DATA_BUFSIZE);
for i := 0 to DATA_BUFSIZE - 1 do
begin
DataBuf.len := DATA_BUFSIZE;
DataBuf.buf := buffer;
end;
Inc(dwEventTotal);
end;
procedure TServer.OperSock;
var
dwIndex, dwBytesTransferred: DWORD;
s: string;
i: integer;
begin
if WSARecv(AcceptSocket, @DataBuf, 1, dwRecvBytes, Flags, @AcceptOverlapped, nil) = SOCKET_ERROR then
if (WSAGetLastError <> WSA_IO_PENDING) then // 返回WSA_IO_PENDING是正常情况,表示IO操作正在进行,不能立即完成
begin
CloseSocket(AcceptSocket);
WSACloseEvent(EventArray[dwEventTotal]);
Exit;
end;
dwIndex := WSAWaitForMultipleEvents(dwEventTotal, @EventArray, FALSE, WSA_INFINITE, FALSE);
dwIndex := dwIndex - WSA_WAIT_EVENT_0;
WSAResetEvent(EventArray[dwIndex]);
WSAGetOverlappedResult(AcceptSocket, @AcceptOverlapped, @dwBytesTransferred, FALSE, Flags);
if dwBytesTransferred = 0 then //传输的字节数,如果为0表示对方套接字已经关闭
begin
CloseSocket(AcceptSocket);
WSACloseEvent(EventArray[dwIndex]); // 关闭事件
Exit;
end;
for i := 0 to DATA_BUFSIZE - 1 do //此处从缓冲区中取出的数据全是乱码,但收到的字节数是对的也就是dwBytesTransferred的对的
if Trim(s) = '' then
s := DataBuf.buf
else
s := s + DataBuf.buf;
form1.ShowStatus(s);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseSocket(AcceptSocket);
end;
end.
******************************************************************************
客户端就简单了,就不列代码了主要就一句:
s := 'hello';
Send(CltSock, s, Length(s), 0);
哪位大虾能帮我看看服务端的问题到底出在哪?