网络头文件、网络库:
打开网络库:
校验版本:
创建socket:
绑定地址端口:
开始监听:
事件选择模型:
WSAEVENT WSAAPI WSACreateEvent();
WSAEVENT转定义是HANDLE, 本质就是void *
内核对象(kernel object ):在操作系统的空间申请的对象, 程序相当于操作系统的函数, 内核对象对于程序来说相当于全局变量 由操作系统申请, 由操作系统访问, 不能定位, 不能修改, void *通用类型指针, 不告诉你真正的类型是什么
调用函数创建, 调用函数释放(内核内存泄漏, 只能重启电脑, 普通内存泄漏重启软件就可以)
BOOL WSAAPI WSACloseEvent(
WSAEVENT hEvent
);
WSAEVENT eventServer = WSACreateEvent();
if (WSA_INVALID_EVENT == eventServer)
{
closesocket(sockServer);
WSACleanup();
return 0;
}
int WSAAPI WSAEventSelect(
SOCKET s,
WSAEVENT hEventObject,
long lNetworkEvents
);
FD_ACCEPT:有客户端连接, 与服务器socket绑定
FD_READ:有客户端发来消息, 与客户端socket绑定, 用按位或并列使用
FD_CLOSE:客户端下线(包含强制下线、正常下线), 与客户端socket绑定
FD_WRITE:可以给客户端发送消息, 与客户端socket绑定, 会在客户端accept后立刻产生, 只产生一次
FD_CONNECT:客户端一方, 与服务器socket绑定
FD_QOS:套接字服务质量状态发生变化消息通知, 例如网络发生拥堵
int WSAAPI WSAIoctl(
SOCKET s,
DWORD dwIoControlCode,
LPVOID lpvInBuffer,
DWORD cbInBuffer,
LPVOID lpvOutBuffer,
DWORD cbOutBuffer,
LPDWORD lpcbBytesReturned,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
char *strOut[2048] = { 0 };
DWORD nLen = 2048;
WSAIcotl(socketServer, SIO_QOS, 0, 0, strOut, nLen, &nLen, NULL, NULL);
FD_ROUTING_INTERFACE_CHANGE:建议应用在重叠I/O中, 数据最优线路改变, 路由接口改变, 要通过WSAIcotl(SIO_ROUTING_INTERFACE_CHANGE)注册使用
FD_ADDRESS_LIST_CHANGE:建议应用在重叠I/O中, 想要接受套接字地址组本地地址列表更改通知, 要通过WSAIcotl(SIO_ADDRESS_LIST_CHANGE)注册使用
if (SOCKET_ERROR == WSAEventSelect(sockServer, eventServer, FD_ACCEPT))
{
int errorcode = WSAGetLastError();
WSACloseEvent(eventServer);
closesocket(sockServer);
WSACleanup();
return 0;
}
struct fd_es_set
{
u_short fd_count;
SOCKET fd_sockarr[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT fd_eventarr[WSA_MAXIMUM_WAIT_EVENTS];
};
DWORD WSAAPI WSAWaitForMultipleEvents(
DWORD cEvents,
const WSAEVENT *lphEvents,
BOOL fWaitAll,
DWORD dwTimeout,
BOOL fAlertable
);
返回值 - WSA_WAIT_EVENT_0表示事件的对象索引
毫秒, 如果没有一个有信号所等待的时间, 超时返回 WSA_WAIT_TIMEOUT
数组下标的运算值:参数3为需要设置为false-->返回值 - WSA_WAAIT_EVENT_0 == 数组下标
WSA_WAIT_IO_COMPLETION:重叠IO的返回值
WSA_WAIT_TIMEOUT:超时, 没有事件有信号, continue
while (1)
{
DWORD nRes = WSAWaitForMultipleEvents(esset.fd_count, esset.fd_eventarr, FALSE, WSA_INFINITE, FALSE);
if (WSA_WAIT_FAILED == nRes)
{
int errorcode = WSAGetLastError();
printf("errorcode : %d\n", errorcode);
break;
}
// 超时使用
/*if (WSA_WAIT_TIMEOUT == nRes)
{
continue;
}*/
DWORD nIndex = nRes - WSA_WAIT_EVENT_0;
}
获取事件类型, 并将事件上的信号重置:accept、recv、close。
int WSAAPI WSAEnumNetworkEvents(
SOCKET s,
WSAEVENT hEventObject,
LPWSANETWORKEVENTS lpNetworkEvents
);
typedef struct _WSANETWORKEVENTS {
long lNetworkEvents;
int iErrorCode[FD_MAX_EVENTS];
} WSANETWORKEVENTS, *LPWSANETWORKEVENTS;
lNetworkEvents:具体的事件(多个事件按位或可能会和一个事件冲突:FD_READ | FD_WRITE == FD_ACCEPT_BIT)
iErrorCode[FD_MAX_EVENTS]:错误码数组, 对应的错误码装在对应的错误宏位置(作为下标, 在事件后面加上_BIT)中
FD_WRITE:只在accept之后立即产生一次, 可以用来初始化客户端初始化
错误:SOCKET_ERROR, WSAGetLastError()
BOOL WSAAPI WSACloseEvent(
WSAEVENT hEvent
);
BOOL WSAAPI WSAResetEvent(
WSAEVENT hEvent
);
BOOL WSAAPI WSASetEvent(
WSAEVENT hEvent
);