Winsock的IOCP的初步应用与理解

winsock最主要的功能基于socket套接字,现在学得还不是特明白,有个初步的大概认识,通过同步异步IO方式,适用于不同的网络,现在主要提出几个winsock的关键点。

在定义sockaddr_in地址结构时,有个地址家族主要注意下,sin_family这个地址家族可以用两个宏来定义,一个AF_INET和PF_INET意思上af_inet为IP协议,pf_inet为TCP协议,一般socket用pf_inet但其实两个值是一样的,也可以通用。

利用ICOP socket通信建立服务端流程大概为

1、调用WSAStartup(MAKEWORD(2,2),wsadata);初始化,载入winsock的动态链接库,然后是动态链接库的结构信息WSADATA,  iMaxSockets为并发的socket的最大数,iMaxUdpDg收发的数据包的最大长度其他的参数无非就是版本信息之类的了。

2、这里我不想去用简单堵塞似recv和select来进行IO操作了,直接用实用性强一点的iocp也就是完成端口的方式进行通信,而且完成端口的IO是用的重叠IO,可以理解为异步的。

所以SOCKET socket=WSASocket(PF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

3、然后初始化地址结构,SOCKADDR_IN,把socket绑定到这个地址上监听,期间把完成端口句柄初始化一下

HANDLE  completePort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);

后面会把这个完成句柄与socket关联起来

4、创建服务处理线程,把线程和完成端口句柄关联起来,即可以接受和发送了。

CreateThread(NULL,0,ServerWorkerThread,completionPort,0,NULL);

5、然后监听IP端口

listen(socket,num);num为监听的线程数

6、然后是等接收客户端的连入的消息了

SOCKET socketHandle=accpet(socket,(SOCKADDR*)addr,num);接收这个地址的socket客户端信息

7、把socket与完成端口句柄关联起来

在这里要特殊注意一下,客户端与服务器交互时,我们可以互传一个单IO数据指针和一个单句柄数据结构(保存有客户端socket信息)进行通信,所以这里我们声明两个数据结构

typedef struct tagPER_IO_DATA
{
 OVERLAPPED Overlapped;
 WSABUF DataBuf;
 char buffer[IODATASIZE];
 DWORD BufferLen;
 int OperationType;   // 可以作为读写的标志,为简单,我忽略了
}PER_IO_DATA, *LPPER_IO_DATA;单IO操作指针  这个数据结构只要保证首位是个OVERLAPPED类型就可以通过首地址去的结构体的指针地址来进行操作。

typedef struct tagPER_HANDLE_DATA
{
    SOCKET Socket;
    xxxxxxxxxx扩展变量

    // 将和这个句柄关联的其他有用信息,尽管放在这里面吧
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;单句柄数据

CreateIoCompletionPort((HANDLE)socketHandle,completionPort,(DWORD)LPPER_HANDLE_DATA,NULL);LPPER_HANDLE_DATA为一个完成端口虚拟键,用来和套接字关联的单句柄数据信息结构,用来获得接受客户端socket的信息的结构。

8、设立接收的接口

WSARecv(socket,&PER_IO_DATA.DataBuf,num,recvbytenum,,&PER_IO_DATA.Overlapped);WSABUF为接收缓冲区结构,num为结构数量,recvbytenum为接收的字节数,overlapped为接受客户端的重叠信息结构。

 9、建立的工作者线程serverworkthread

循环里while(true)

通过GetQueuedCompletionStatus(completionPort,&bytenum,(LPDWORD)&PER_HANDLE_DATA.socket,(LPOVERLAPPED*)&PER_IO_DATA,INFINITE)取得完成端口的结果

这里最好通过线程互斥锁来锁定线程,先createMutex一个互斥锁,第二个参数为false为创建的句柄为有信号的,然后用WaitForSingleObject()检查互斥锁的信号,然后用ReleaseMutex()释放占有权不然其它线程中的WaitForSingleObject()将阻塞。

返回成功之后取得IO数据然后重置IO

ZeroMemory清空PER_IO_DATA数据

再赋值PER_IO_DATA.databuf.buf=PER_IO_DATA.buffer

PER_IO_DATA.databuf.len=SIZE

然后再继续接收WSARecv();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值