#define _CRT_SECURE_NO_WARNINGS
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib,"Ws2_32.lib")
//存储所有socket和event的结构体
typedef struct fd_event_socket_set
{
unsigned short count;
SOCKET all_sock[WSA_MAXIMUM_WAIT_EVENTS];
WSAEVENT all_event[WSA_MAXIMUM_WAIT_EVENTS];
};
fd_set fd_set_socks;//装服务端和多个客户端的集合
struct fd_event_socket_set fd_es_set[20];//20组
BOOL WINAPI fun(DWORD dw_ctrl_type)
{
switch (dw_ctrl_type)
{
case CTRL_CLOSE_EVENT:
{
{
/*释放所有的socket*/
for (int j = 0; j < 20;j++)
{
for (int i = 0; i < fd_es_set[j].count; i++)
{
closesocket(fd_es_set[j].all_sock[i]);
WSACloseEvent(fd_es_set[j].all_event[i]);
}
}
}
}
break;
default:
break;
}
return TRUE;
}
int main(int argc, char* argv[])
{
SetConsoleCtrlHandler(fun, TRUE);
/*打开网络库*/
WORD ws_verson = MAKEWORD(2, 2);
WSADATA wd_sock_msg;
int ret = WSAStartup(ws_verson, &wd_sock_msg);
if (0 != ret)
{
switch (ret)
{
case WSASYSNOTREADY:
printf("重启下电脑试试,或者检查网络库!");
break;
case WSAVERNOTSUPPORTED:
printf("请更新网络库!");
break;
case WSAEPROCLIM:
printf("请重新启动!");
break;
case WSAEINPROGRESS:
printf("请尝试关掉不必要的软件,为当前网络运行提供充足资源!");
break;
case WSAEFAULT:
printf("参数错误!");
break;
default:
break;
}
return 0;
}
printf("网络库打开成功!\n");
/*检查版本*/
if (2 != LOBYTE(wd_sock_msg.wVersion) || //地位-》得到主版本
2 != HIBYTE(wd_sock_msg.wVersion)) //高位-》得到副版本
{
//说明版本不对,要关闭网络库
WSACleanup();
return -1;
}
printf("网络库版本号:(%d,%d)\n", LOBYTE(wd_sock_msg.wVersion), HIBYTE(wd_sock_msg.wVersion));
/*创建套接字*/
SOCKET socket_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == socket_server)
{
printf("socket_server created failed,error_code:%d\n", WSAGetLastError());
WSACleanup();//关闭网络库
return -1;
}
else
printf("socket_server created success,return code:%d\n", socket_server);
/*绑定地址*/
struct sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(12345);
si.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int res_bind = bind(socket_server, (const struct sockaddr *) &si, sizeof(si));
if (SOCKET_ERROR == res_bind)
{
printf("bind failed,error_code:%d\n", WSAGetLastError());
closesocket(socket_server);
WSACleanup();//关闭网络库
return -1;
}
else
printf("bind success,return code:%d\n", res_bind);
/*监听listen*/
int res_listen = listen(socket_server, SOMAXCONN);
if (SOCKET_ERROR == res_listen)
{
printf("listen failed,error_code:%d\n", WSAGetLastError());
closesocket(socket_server);
WSACleanup();//关闭网络库
return -1;
}
else
printf("listen success,return code:%d\n", res_listen);
/*event select 事件*/
//1.创建事件
WSAEVENT server_event = WSACreateEvent();
if (WSA_INVALID_EVENT == server_event)
{
printf("event_server error,error_code:%d\n", WSAGetLastError());
closesocket(socket_server);
WSACleanup();//关闭网络库
return -1;
}
//2.将服务端绑定并投递
int res_server_event_select = WSAEventSelect(socket_server, server_event, FD_ACCEPT);
if (SOCKET_ERROR == res_server_event_select)
{
printf("server_event_select error,error_code:%d\n", WSAGetLastError());
//关闭、释放事件
BOOL colse_event_flag = WSACloseEvent(server_event);
if (TRUE == colse_event_flag)
{
printf("server_event close success\n");
}
else if (FALSE == colse_event_flag)
{
printf("server_event close failed,error_code:%d\n", WSAGetLastError());
}
//关闭socket
closesocket(socket_server);
//关闭网络库
WSACleanup();//关闭网络库
return -1;
}
/*询问事件*/
//将服务端事件装进去
fd_es_set[0].all_event[fd_es_set[0].count] = server_event;
fd_es_set[0].all_sock[fd_es_set[0].count] = socket_server;
fd_es_set[0].count++;
while (1)
{
for (int j = 0; j < 20; j++)
{
if (0 == fd_es_set[j].count)
{
continue;
}
//先在一组里面找到有事件的那个
DWORD res_wait = WSAWaitForMultipleEvents(fd_es_set[j].count,
fd_es_set[j].all_event,
FALSE,
0,
FALSE);
if (WSA_WAIT_FAILED == res_wait)//出错了
{
printf("WSAWaitForMultipleEvents error, error_code:%d\n", WSAGetLastError());
continue;
}
if (WSA_WAIT_TIMEOUT == res_wait)
{
continue;
}
DWORD index = res_wait - WSA_WAIT_EVENT_0;//先得到第一个触发事件的客户端的下标
for (int i = index; i < fd_es_set[j].count; i++)
{
//一次只询问一个
DWORD res_wait_event = WSAWaitForMultipleEvents(1,
&fd_es_set[j].all_event[i],
FALSE,
0,/*不等待,有没有信号都立即返回*/
FALSE);
if (WSA_WAIT_FAILED == res_wait_event)//出错了
{
printf("WSAWaitForMultipleEvents error, error_code:%d\n", WSAGetLastError());
continue;
}
//超时
if (WSA_WAIT_TIMEOUT == res_wait_event)
{
//printf("WSAWaitForMultipleEvents timeout\n");
continue;
}
//等到下标对应的具体操作
WSANETWORKEVENTS network_events;
int res_enum_events = WSAEnumNetworkEvents(fd_es_set[j].all_sock[i],
fd_es_set[j].all_event[i],
&network_events);
if (SOCKET_ERROR == res_enum_events)
{
printf("WSAEnumNetworkEvents error, error_code:%d\n", res_enum_events);
break;
}
/*事件分类处理*/
//处理FD_ACCEPT
if (network_events.lNetworkEvents & FD_ACCEPT)
{
if (0 == network_events.iErrorCode[FD_ACCEPT_BIT])
{
//正常处理
SOCKET socket_client = accept(fd_es_set[j].all_sock[i], NULL, NULL);
if (INVALID_SOCKET == socket_client)
{
continue;
}
//为客户端创建事件对象
WSAEVENT wsa_client_event = WSACreateEvent();
if (WSA_INVALID_EVENT == wsa_client_event)
{
closesocket(socket_client);
continue;
}
//将客户端投递给系统 处理FD_READ FD_CLOSE FD_WRITE
int res_client_event_select = WSAEventSelect(socket_client,
wsa_client_event,
FD_READ | FD_CLOSE | FD_WRITE);
if (SOCKET_ERROR == res_client_event_select)
{
printf("client_event_select error,error_code:%d\n", WSAGetLastError());
//关闭、释放事件
BOOL colse_event_flag = WSACloseEvent(wsa_client_event);
if (TRUE == colse_event_flag)
{
printf("wsa_client_event close success\n");
}
else if (FALSE == colse_event_flag)
{
printf("wsa_client_event close failed,error_code:%d\n", WSAGetLastError());
}
//关闭socket
closesocket(socket_client);
//关闭网络库
WSACleanup();//关闭网络库
return -1;
}
for (int k = 0; k < 20; k++)
{
if (fd_es_set[k].count < 64)
{
//装进结构体
fd_es_set[k].all_sock[fd_es_set[k].count] = socket_client;
fd_es_set[k].all_event[fd_es_set[k].count] = wsa_client_event;
fd_es_set[k].count++;
break;
}
}
printf("accept event\n");
}
else
{
printf("network_events FD_ACCEPT | socket error, error_code:%d\n",
network_events.iErrorCode[FD_ACCEPT_BIT]);
continue;
}
}
//处理FD_WRITE
if (network_events.lNetworkEvents & FD_WRITE)
{
if (0 == network_events.iErrorCode[FD_WRITE_BIT])
{
//初始化
//int res_send = send(fd_es_set.all_sock[index], "connect success",
// sizeof("connect success") - 1, 0);//sizeof()包括'\0'
int res_send = send(fd_es_set[j].all_sock[i], "connect success",
strlen("connect success"), 0);//strlen()不包括'\0'
if (SOCKET_ERROR == res_send)
{
printf("send error, error_code:%d\n", WSAGetLastError());
continue;
}
printf("write event\n");
}
else
{
printf("network_events FD_WRITE | socket error, error_code:%d\n",
network_events.iErrorCode[FD
评论0