NoteDeep
#define _CRT_SECURE_NO_WARNINGS

#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

#include <stdio.h>
#include <stdlib.h>

fd_set allsockets;
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_CLOSE_EVENT: // 退出
for (u_int i = 0; i < allsockets.fd_count; i++)
{
closesocket(allsockets.fd_array[i]);
}

WSACleanup();
break;
}

return TRUE;
}

int main()
{
SetConsoleCtrlHandler(HandlerRoutine, TRUE);

WORD wdVersion = MAKEWORD(2, 2); // 版本号, 高字节:1, 低字节:2
WSADATA wdSockMsg;
int nRes = WSAStartup(wdVersion, &wdSockMsg); // LP/P 开头的是需要地址

if (nRes)
{
switch (nRes)
{
case WSASYSNOTREADY:
printf("重启电脑或检查网络库!\n");
break;
case WSAVERNOTSUPPORTED:
printf("使用的版本不支持, 请更新网络库\n");
break;
case WSAEINPROGRESS:
printf("请重新启动\n");
break;
case WSAEPROCLIM:
printf("请关闭不必要的软件\n");
break;
case WSAEFAULT:
break;
default:
break;
}

return 0;

}

// 校验版本
if (2 != HIBYTE(wdSockMsg.wVersion) || 2 != LOBYTE(wdSockMsg.wVersion))
{
// 打开的版本不对
// 清理/关闭网络库
WSACleanup();
return 0;
}

SOCKET sockServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (INVALID_SOCKET == sockServer)
{
int errorcode = WSAGetLastError();
WSACleanup();
return 0;
}

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 bres = bind(sockServer, (const sockaddr *)&si, sizeof(sockaddr_in));

if (SOCKET_ERROR == bres)
{
int errorcode = WSAGetLastError();

closesocket(sockServer);
WSACleanup();
return 0;
}

if (SOCKET_ERROR == listen(sockServer, SOMAXCONN))
{
int errorcode = WSAGetLastError();

closesocket(sockServer);
WSACleanup();
return 0;
}

FD_ZERO(&allsockets);
FD_SET(sockServer, &allsockets);

while (1)
{
fd_set readpsockets = allsockets;
fd_set writesockets = allsockets;
FD_CLR(sockServer, &writesockets);
// 可以删除服务器socket, 也可以不删
fd_set errorsockets = allsockets;

// 时间段
timeval ti;
ti.tv_sec = 0;
ti.tv_usec = 0;

int nRes = select(0, &readpsockets, &writesockets, &errorsockets, &ti);

if (0 == nRes)
{
// 没有响应的socket
continue;
}
else if (nRes > 0)
{
// 第四个参数
for (u_int i = 0; i < errorsockets.fd_count; i++)
{
char buf[100] = { 0 };
int len = 99;
int res = getsockopt(errorsockets.fd_array[i], SOL_SOCKET, SO_ERROR, buf, &len);

if (SOCKET_ERROR == res)
{
int errorcode = WSAGetLastError();
printf("无法获取错误信息.\n");
}
}

// 第三个参数
for (u_int i = 0; i < writesockets.fd_count; i++)
{
// 可写的socket没有服务器本身
if (writesockets.fd_array[i] == sockServer)
{
printf("find sockserver!\n");
}
else
{
int res = send(writesockets.fd_array[i], "ok", strlen("ok"), 0);
if (SOCKET_ERROR == res)
{
// 向下线的客户端发送消息也会返回SOCKET_ERROR
int errorcode = WSAGetLastError();
}

}
}

// 第二个参数
for (u_int i = 0; i < readpsockets.fd_count; i++)
{
if (readpsockets.fd_array[i] == sockServer)
{
// accept
SOCKET socketClient = accept(sockServer, NULL, NULL);
if (INVALID_SOCKET == socketClient)
{
// 连接出错
continue;
}
// 将新的socket放入socket集合
FD_SET(socketClient, &allsockets);
printf("newclient accept.\n");
}
else
{
char strBuf[1500] = { 0 };
// 客户端发来消息
int nRecv = recv(readpsockets.fd_array[i], strBuf, 1500, 0);
if (SOCKET_ERROR == nRecv)
{
int errorcode = WSAGetLastError();
// 客户端强制下线错误码:10054
switch (errorcode)
{
case 10054:
FD_CLR(readpsockets.fd_array[i], &allsockets);
closesocket(readpsockets.fd_array[i]);
printf("client force exit.\n");
break;
default:
printf("other errorcode.\n");
break;
}

}
else if (nRecv == 0)
{
// 客户端正常下线
// 1.从集合中去掉 2.释放socket
//SOCKET socketTemp = tempsockets.fd_array[i]
FD_CLR(readpsockets.fd_array[i], &allsockets);
closesocket(readpsockets.fd_array[i]);
printf("client quit.\n");
}
else
{
// 接收数据
printf("Recv:%s\n", strBuf);
}
}
}
}
else
{
int errorcode = WSAGetLastError();
// 必须发生不可调和的错误时才能关闭服务器(或自己定义推出条件)
break;
}
}
// 释放所有socket
for (u_int i = 0; i < allsockets.fd_count; i++)
{
closesocket(allsockets.fd_array[i]);
}

WSACleanup();

system("pause");
return 0;
}

评论列表