完成端口的发送问题 求救 ( 积分: 100 )

  • 主题发起人 king1994gw
  • 开始时间
K

king1994gw

Unregistered / Unconfirmed
GUEST, unregistred user!
刚看完成端口 接收的是有例子了 所以想把它改为发送的 却发现没那么简单 象connect 或给地址族赋值 我不知道放在主线程还是工作线程 下面的程序运行有问题 根本不能发送 请各位高手赐教呀
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:eek:verlapped;
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,sendbytes: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:=inet_addr(pchar('192.168.0.2'));
internetaddr.sin_port:=htons(port);
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:=listen;
if (createiocompletionport(listen,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.buffer:='wudi';
periodata.databuf.buf:=@periodata.buffer;
flags:=0;
connect(listen,internetaddr,sizeof(internetaddr));
if (wsasend(listen,@(periodata.databuf),1,@sendbytes,0,@(periodata.overlapped),nil)=socket_error) then
begin
if (wsagetlasterror<>error_io_pending) then
begin
printf('wsarecvfailed%d',wsagetlasterror());
exit;
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) and (periodata.bytessend=0) then
begin
PerIoData.BytesREC:= BytesTransferred;
periodata.bytessend:= 0;
end
else
begin
periodata.bytesrec:=0;
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;
printf(periodata.buffer,periodata.databuf.len);
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 (wsasend(perhandledata.socket,@(periodata.databuf),1,@sendbytes,0,@(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.
 
又是三无代码。
 
数据的连接不是放在主线程,也不是放在工作线程,而是谁要建立连接,就在谁的线程里面,建立好连接以后,会得到消息,getqueuedcompletionstatus
per_io_operation_data=packed record
overlapped:eek:verlapped;
databuf:twsabuf;
buffer:array[0..data_bufsize]of char;
bytessend:dword;
bytesrec:dword;
end;
这个数据结构少了一个字段,就是eventType
我们必须更具这个字段来传递,到底改做啥了。
比如,你连接的时候,设置eventype:=etconnect (etconnect是你自己定义的常量)
当getqueuedcompletionstatus得到消息以后,就检查这个字段,发现事etconnect说明事你自己建立连接成功,你一般来说就发送数据,
这个时候,你设置eventtype=eesend
然后调研wsasend发送数据,

还有一般来说,服务器只是接受连接,然后,读取数据,发送数据,断开链接,而较少的去主动连接。
现在这么多应用层协议,似乎只有FTP有主动连接
 
谢谢 超级菜的一个问题 给国家丢脸了 我这个代码是网上找的一个模型 刚看完成端口 也不知道 有eventtype 谢谢了
 
顶部