主题:[讨论]关于网上的完成端口客户端再次登陆不能发送问题
刚看完成端口有点问题 下面是我网上找来的完成端口模型的代码,我配了个简单的客户端与与完成端口模型通信 客户端第一次能发送数据 但当关掉客户端 再打开客户端与完成端口模型通信 就不能发送数据了 点发送按钮 就直接无响应了 不知道是为什么呀
服务器
unit Unit2;
interface
uses Windows, unit1, WinSock, Sysutils;
const
port=5150;
data_bufsize=8192;
type
lpvoid=pointer;
lpper_io_operation_data=^per_io_operation_data;
per_io_operation_data=packed record
overlapped:overlapped;
databuf:twsabuf;
buffer:array[0..data_bufsize]of char;
bytessend:dword;
bytesrec:dword;
end;
lpper_handle_data=^per_handle_data;
per_handle_data=packed record
socket:tsocket;
end;
procedure main;
implementation
function serverworkerthread(completionportid:lpvoid):dword;stdcall;forward;
procedure printf(fmt:string;num:integer);
begin
writeln(format(fmt,[num]));
end;
procedure main;
var
internetaddr:sockaddr_in;
listen:tsocket;
accept:tsocket;
completionport:thandle;
systeminfo:system_info;
perhandledata:lpper_handle_data;
periodata:lpper_io_operation_data;
i:integer;
recvbytes:dword;
flags:dword;
threadid:dword;
wsadata:twsadata;
ret:dword;
threadhandle:thandle;
begin
ret:=wsastartup($0202,wsadata);
if (ret<>0) then
begin
printf('wsas %d',ret);
exit;
end;
completionport:=createiocompletionPort(INVALID_HANDLE_VALUE,0,0,0);
if (CompletionPort=0) then
begin
printf('createioerror:%d',getlasterror());
exit;
end;
getsysteminfo(systeminfo);
for i:=0 to systeminfo.dwNumberOfProcessors*2-1 do
begin
threadhandle:=createthread(nil,0,@serverworkerthread,pointer(completionport),0,threadid);
if (threadhandle=0) then
begin
printf('c',getlasterror());
exit;
end;
closehandle(threadhandle);
end;
listen:=wsasocket(af_inet,sock_stream,0,nil,0,wsa_flag_overlapped);
if (listen=invalid_socket) then
begin
printf('wsa',wsagetlasterror());
exit;
end;
internetaddr.sin_family:=af_inet;
internetaddr.sin_addr.S_addr:=htonl(inaddr_any);
internetaddr.sin_port:=htons(port);
if (bind(listen,internetaddr,sizeof(internetaddr))=socket_error) then
begin
printf('bind',wsagetlasterror());
exit;
end;
if (winsock.listen(listen,5)=socket_error) then
begin
printf('listen',wsagetlasterror());
exit;
end
else
begin
printf('serverlisten',port);
end;
while (true) do
begin
accept:=wsaaccept(listen,nil,nil,nil,0);
if (accept=socket_error) then
begin
printf('wsaaccept',wsagetlasterror());
exit;
end;
perhandledata:=lpper_handle_data(globalalloc(gptr,sizeof(per_handle_data)));
if (perhandledata=nil) then
begin
printf('glo',wsagetlasterror());
exit;
end;
printf('socket numble%d',accept);
perhandledata.socket:=accept;
if (createiocompletionport(accept,completionport,dword(perhandledata),0)=0) then
begin
printf('createiocp%d',wsagetlasterror());
exit;
end;
periodata:=lpper_io_operation_data(globalalloc(gptr,sizeof(per_io_operation_data)));
if (periodata=nil) then
begin
printf('glo%d',wsagetlasterror());
exit;
end;
zeromemory(@periodata.overlapped,sizeof(overlapped));
periodata.bytessend:=0;
periodata.bytesrec:=0;
periodata.databuf.len:=data_bufsize;
periodata.databuf.buf:=@periodata.buffer;
flags:=0;
if (wsarecv(accept,@(periodata.databuf),1,@recvbytes,@flags,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror<>error_io_pending) then
begin
printf('wsarecvfailed%d',wsagetlasterror());
exit;
end
end;
end;
end;
function serverworkerthread(completionportid:lpvoid):dword;stdcall;
var
CompletionPort: THANDLE;
BytesTransferred: DWORD ;
PerHandleData: LPPER_HANDLE_DATA ;
PerIoData: LPPER_IO_OPERATION_DATA ;
SendBytes, RecvBytes: DWORD;
Flags: DWORD ;
begin
completionport:=thandle(completionportid);
result:=0;
while(true) do
begin
if (getqueuedcompletionstatus(completionport,bytestransferred,dword(perhandledata),poverlapped(periodata),infinite)=false) then
begin
printf('get%d',getlasterror());
exit;
end;
if (bytestransferred=0) then
begin
printf('closingsocket%d\',perhandledata.socket);
if (closesocket(perhandledata.socket)=socket_error) then
begin
printf('closesocketerror%d',wsagetlasterror());
exit;
end;
globalfree(dword(perhandledata));
globalfree(dword(periodata));
continue;
end;
if (periodata.bytesrec=0) then
begin
PerIoData.BytesREC:= BytesTransferred;
periodata.bytessend:= 0;
end
else
begin
periodata.bytessend:= periodata.bytessend+bytestransferred;
end;
if (periodata.bytesrec>periodata.bytessend) then
begin
zeromemory(@(periodata.overlapped),sizeof(overlapped));
periodata.databuf.buf:= periodata.buffer+periodata.bytessend;
periodata.databuf.len:= periodata.bytesrec-periodata.bytessend;
if (wsasend(perhandledata.socket,@(periodata.databuf),1,@sendbytes,0,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
printf('wsasend%d',wsagetlasterror());
exit
end;
end;
end
else
begin
periodata.bytesrec:= 0;
flags:= 0;
zeromemory(@(periodata.overlapped),sizeof(overlapped));
periodata.databuf.len:= data_bufsize;
periodata.databuf.buf:= @periodata.buffer;
if (wsarecv(perhandledata.socket,@(periodata.databuf),1,@recvbytes,@flags,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
printf('wsa%d',wsagetlasterror());
exit;
end;
end;
end;
end;
end;
end;
end.
客户端
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,winsock, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
wsadata:twsadata;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
errorcode:integer;
begin
errorcode:=wsastartup($0101,wsadata);
if errorcode<> 0 then
begin
showmessage('jiazaifaile');
exit;
end;
end;
{ tsocketreadthread }
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
wsacleanup;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
buf:array[0..10] of char;
rebuf:array[0..10] of char;
sa:sockaddr_in;
skc:tsocket;
ret:integer;
r:string;
begin
skc:=socket(pf_inet,sock_stream,ipproto_tcp);
if skc=socket_error then
begin
showmessage('shibai');
exit;
end;
sa.sin_family:=pf_inet;
sa.sin_port:=htons(5150);
sa.sin_addr.S_addr:=inet_addr(pchar('192.168.0.2'));
connect(skc,sa,sizeof(sa));
r:='hehehe';
lstrcpy(buf,pchar(r));
send(skc,buf,10*sizeof(char),0);
ret:=recv(skc,rebuf,256,0);
if ret>0 then memo1.Lines.Add(rebuf);
end;
end.[?][?]
服务器
unit Unit2;
interface
uses Windows, unit1, WinSock, Sysutils;
const
port=5150;
data_bufsize=8192;
type
lpvoid=pointer;
lpper_io_operation_data=^per_io_operation_data;
per_io_operation_data=packed record
overlapped:overlapped;
databuf:twsabuf;
buffer:array[0..data_bufsize]of char;
bytessend:dword;
bytesrec:dword;
end;
lpper_handle_data=^per_handle_data;
per_handle_data=packed record
socket:tsocket;
end;
procedure main;
implementation
function serverworkerthread(completionportid:lpvoid):dword;stdcall;forward;
procedure printf(fmt:string;num:integer);
begin
writeln(format(fmt,[num]));
end;
procedure main;
var
internetaddr:sockaddr_in;
listen:tsocket;
accept:tsocket;
completionport:thandle;
systeminfo:system_info;
perhandledata:lpper_handle_data;
periodata:lpper_io_operation_data;
i:integer;
recvbytes:dword;
flags:dword;
threadid:dword;
wsadata:twsadata;
ret:dword;
threadhandle:thandle;
begin
ret:=wsastartup($0202,wsadata);
if (ret<>0) then
begin
printf('wsas %d',ret);
exit;
end;
completionport:=createiocompletionPort(INVALID_HANDLE_VALUE,0,0,0);
if (CompletionPort=0) then
begin
printf('createioerror:%d',getlasterror());
exit;
end;
getsysteminfo(systeminfo);
for i:=0 to systeminfo.dwNumberOfProcessors*2-1 do
begin
threadhandle:=createthread(nil,0,@serverworkerthread,pointer(completionport),0,threadid);
if (threadhandle=0) then
begin
printf('c',getlasterror());
exit;
end;
closehandle(threadhandle);
end;
listen:=wsasocket(af_inet,sock_stream,0,nil,0,wsa_flag_overlapped);
if (listen=invalid_socket) then
begin
printf('wsa',wsagetlasterror());
exit;
end;
internetaddr.sin_family:=af_inet;
internetaddr.sin_addr.S_addr:=htonl(inaddr_any);
internetaddr.sin_port:=htons(port);
if (bind(listen,internetaddr,sizeof(internetaddr))=socket_error) then
begin
printf('bind',wsagetlasterror());
exit;
end;
if (winsock.listen(listen,5)=socket_error) then
begin
printf('listen',wsagetlasterror());
exit;
end
else
begin
printf('serverlisten',port);
end;
while (true) do
begin
accept:=wsaaccept(listen,nil,nil,nil,0);
if (accept=socket_error) then
begin
printf('wsaaccept',wsagetlasterror());
exit;
end;
perhandledata:=lpper_handle_data(globalalloc(gptr,sizeof(per_handle_data)));
if (perhandledata=nil) then
begin
printf('glo',wsagetlasterror());
exit;
end;
printf('socket numble%d',accept);
perhandledata.socket:=accept;
if (createiocompletionport(accept,completionport,dword(perhandledata),0)=0) then
begin
printf('createiocp%d',wsagetlasterror());
exit;
end;
periodata:=lpper_io_operation_data(globalalloc(gptr,sizeof(per_io_operation_data)));
if (periodata=nil) then
begin
printf('glo%d',wsagetlasterror());
exit;
end;
zeromemory(@periodata.overlapped,sizeof(overlapped));
periodata.bytessend:=0;
periodata.bytesrec:=0;
periodata.databuf.len:=data_bufsize;
periodata.databuf.buf:=@periodata.buffer;
flags:=0;
if (wsarecv(accept,@(periodata.databuf),1,@recvbytes,@flags,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror<>error_io_pending) then
begin
printf('wsarecvfailed%d',wsagetlasterror());
exit;
end
end;
end;
end;
function serverworkerthread(completionportid:lpvoid):dword;stdcall;
var
CompletionPort: THANDLE;
BytesTransferred: DWORD ;
PerHandleData: LPPER_HANDLE_DATA ;
PerIoData: LPPER_IO_OPERATION_DATA ;
SendBytes, RecvBytes: DWORD;
Flags: DWORD ;
begin
completionport:=thandle(completionportid);
result:=0;
while(true) do
begin
if (getqueuedcompletionstatus(completionport,bytestransferred,dword(perhandledata),poverlapped(periodata),infinite)=false) then
begin
printf('get%d',getlasterror());
exit;
end;
if (bytestransferred=0) then
begin
printf('closingsocket%d\',perhandledata.socket);
if (closesocket(perhandledata.socket)=socket_error) then
begin
printf('closesocketerror%d',wsagetlasterror());
exit;
end;
globalfree(dword(perhandledata));
globalfree(dword(periodata));
continue;
end;
if (periodata.bytesrec=0) then
begin
PerIoData.BytesREC:= BytesTransferred;
periodata.bytessend:= 0;
end
else
begin
periodata.bytessend:= periodata.bytessend+bytestransferred;
end;
if (periodata.bytesrec>periodata.bytessend) then
begin
zeromemory(@(periodata.overlapped),sizeof(overlapped));
periodata.databuf.buf:= periodata.buffer+periodata.bytessend;
periodata.databuf.len:= periodata.bytesrec-periodata.bytessend;
if (wsasend(perhandledata.socket,@(periodata.databuf),1,@sendbytes,0,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
printf('wsasend%d',wsagetlasterror());
exit
end;
end;
end
else
begin
periodata.bytesrec:= 0;
flags:= 0;
zeromemory(@(periodata.overlapped),sizeof(overlapped));
periodata.databuf.len:= data_bufsize;
periodata.databuf.buf:= @periodata.buffer;
if (wsarecv(perhandledata.socket,@(periodata.databuf),1,@recvbytes,@flags,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
if (wsagetlasterror()<>error_io_pending) then
begin
printf('wsa%d',wsagetlasterror());
exit;
end;
end;
end;
end;
end;
end;
end.
客户端
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,winsock, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
wsadata:twsadata;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
errorcode:integer;
begin
errorcode:=wsastartup($0101,wsadata);
if errorcode<> 0 then
begin
showmessage('jiazaifaile');
exit;
end;
end;
{ tsocketreadthread }
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
wsacleanup;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
buf:array[0..10] of char;
rebuf:array[0..10] of char;
sa:sockaddr_in;
skc:tsocket;
ret:integer;
r:string;
begin
skc:=socket(pf_inet,sock_stream,ipproto_tcp);
if skc=socket_error then
begin
showmessage('shibai');
exit;
end;
sa.sin_family:=pf_inet;
sa.sin_port:=htons(5150);
sa.sin_addr.S_addr:=inet_addr(pchar('192.168.0.2'));
connect(skc,sa,sizeof(sa));
r:='hehehe';
lstrcpy(buf,pchar(r));
send(skc,buf,10*sizeof(char),0);
ret:=recv(skc,rebuf,256,0);
if ret>0 then memo1.Lines.Add(rebuf);
end;
end.[?][?]