InitSock.h头文件
#pragma once
#include <winsock2.h>
#pragma comment(lib,"ws2_32") //链接ws2_32.lib库
class CInitSock
{
public:
CInitSock(BYTE minorVer=2, BYTE major = 2) //载入Winsock库
{
WSADATA wsaData;
WORD sockVersion = MAKEWORD(minorVer, major);
if (::WSAStartup(sockVersion, &wsaData) != 0)
{
return;
}
}
~CInitSock()
{
::WSACleanup(); //释放Winsock库
}
};
#include "InitSock.h"
#include <iostream>
using namespace std;
//select的好处是程序能够在单线程内同时处理多个套接字连接
int main()
{
CInitSock initSock; //初始化套接字库
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建监听套接字
sockaddr_in addr;
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = htons(4567);
//套机字与本地机器绑定
if (::bind(sListen, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
cout << "Faild bind" << endl;
return -1;
}
::listen(sListen, 5);//监听 最多等待5个连接
//select模型
fd_set fdSocket; //套接字集合 ,默认最大值FD_SETSIZE
FD_ZERO(&fdSocket); //初始化fd_set集合,集合在使用前应该清空
FD_SET(sListen, &fdSocket); //将套接字添加到集合
while (1)
{
fd_set fdRead = fdSocket; //将一个套接字拷贝赋给select函数
//用于接收数据
int iRet = ::select(0, &fdRead, NULL, NULL, NULL); //参数1:忽略,仅为了与Berkeley套机字兼容
//参数2:用来检查可读性
//参数3:用来检查可写性
//参数4:用来检查错误
//参数5:用来设置等待时间,NULL表示一直阻塞等待
//返回值:0表示超时,失败返回SOCKET_ERROR,调用成功返回发生网络事件的套接字数量总和
if (iRet > 0) //返回成功fdRead套接字集合会有变化
{
for (int i = 0; i < fdRead.fd_count; i++)
{
if (FD_ISSET(fdSocket.fd_array[i], &fdRead)) //检查fdSocket.fd_arry[i]是不是faRead的成员函数,成功返回TRUE
{
if (fdSocket.fd_array[i] == sListen) //监听套接字接收到新连接
{
if (fdSocket.fd_count < FD_SETSIZE) //判断是否小于select的最大数量
{
sockaddr_in addrRemote;
int iLen = sizeof(addrRemote);
SOCKET sNew = ::accept(sListen, (SOCKADDR*)&addrRemote, &iLen); //创建套接字与客户端通信
FD_SET(sNew, &fdSocket); //新接收的连接添加到套接字集合
printf("接收到连接(%s)\n", ::inet_ntoa(addrRemote.sin_addr));
}
else
{
//超过select的最大数量
printf("Too much connections \n");
continue;
}
}
else
{
char cText[256];
int iRecv = ::recv(fdSocket.fd_array[i], cText, strlen(cText),0);
if (iRecv > 0)
{
cText[iRecv] = '\0';
printf("接收的数据:%s\n", cText);
}
else
{
::closesocket(fdSocket.fd_array[i]); //连接关闭、重启、关闭
FD_CLR(fdSocket.fd_array[i], &fdSocket); //从套接字集合fdSocket中删除fdSocket.fd_array[i]
}
}
}
}
}
else
{
printf("Faild select \n");
}
}
return 0;
}