关于WIN2000下利用重叠I/O模型编写WSOCK2。0下的网络程序的问题,感兴趣的来看看(100分)

  • 主题发起人 主题发起人 阿伟~
  • 开始时间 开始时间

阿伟~

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);

哪位大虾能帮我看看服务端的问题到底出在哪?
 
Send(CltSock,s[1],Length(s),0);
还有呀,试试用完成例程吧,结构清晰也容易控制。
 
呵呵,兄弟这里采用的是“事件通知”的方法控制的,完成例程我会了解的,但我现在想解决眼前遇到的问题
 
Send(CltSock,s[1],Length(s),0);
 
晕,这里有个笔误,寒~~~~~~~谢谢楼上兄弟提点,马上结帖
 
接受答案了.
 
后退
顶部