📄 serversocket.cpp
字号:
AfxMessageBox("_WaitForCompletionThread 发生异常,线程将退出!");
break;
}
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 构造函数,初始化SOCKET数组
//
////////////////////////////////////////////////////////////////////////////////////
CServerSocket::CServerSocket(void)
{
for(int i=0;i<MAX_SOCKET;i++)
{
sockArray[i] = INVALID_SOCKET;
}
}
////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 析构,释放资源
//
////////////////////////////////////////////////////////////////////////////////////
CServerSocket::~CServerSocket(void)
{
TRACE("CServerSocket 析构!");
StopListening();
WSACleanup();
}
//////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 开始监听过程
//
// 初始化监听SOCKET,绑定地址,启动监听线程,都是老套路,不用多说:)
//
///////////////////////////////////////////////////////////////////////////////////////
int CServerSocket::StartListening(const UINT& port)
{
m_nPort = port;
WSADATA wsaData;
int nRet;
nRet=WSAStartup(MAKEWORD(2,2),&wsaData);
if(nRet!=0)
{
AfxMessageBox("Load winsock2 failed");
WSACleanup();
return -1;
}
sockListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建服务套接字(TCP)
SOCKADDR_IN ServerAddr; //分配端口及协议族并绑定
ServerAddr.sin_family=AF_INET;
ServerAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);
ServerAddr.sin_port=htons(port);
nRet=bind(sockListen,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr)); // 绑定套接字
if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Bind Socket Fail!");
closesocket(sockListen);
return -1;
}
nRet=listen(sockListen,1); //开始监听,并设置监听客户端数量
if(nRet==SOCKET_ERROR)
{
AfxMessageBox("Listening Fail!");
return -1;
}
pServerListenThread = AfxBeginThread( // 启动监听线程
_ServerListenThread,
this
);
pWaitForCompletionThread = AfxBeginThread(
_WaitForCompletionThread,
this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED,NULL
);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 停止监听,关闭线程,释放资源
//
///////////////////////////////////////////////////////////////////////////////////////
int CServerSocket::StopListening()
{
if(pServerListenThread != NULL)
{
DWORD dwStatus;
::GetExitCodeThread(pServerListenThread->m_hThread, &dwStatus);
if (dwStatus == STILL_ACTIVE)
{
delete pServerListenThread;
pServerListenThread = NULL;
}
}
if(pWaitForCompletionThread != NULL)
{
DWORD dwStatus;
::GetExitCodeThread(pWaitForCompletionThread->m_hThread, &dwStatus);
if (dwStatus == STILL_ACTIVE)
{
delete pWaitForCompletionThread;
pWaitForCompletionThread = NULL;
}
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 枚举SOCKET数组,获得一个空闲的SOCKET的索引号
//
// Hints: 可以利用自己定义的数据结构来获得更好的算法,但是这里考虑到代码复杂性,则略过
//
////////////////////////////////////////////////////////////////////////////////////////////
int CServerSocket::GetEmptySocket()
{
for(int i=0;i<MAX_SOCKET;i++)
{
if(sockArray[i]==INVALID_SOCKET)
{
return i;
}
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 根据回调函数中的Overlapped参数,判断是哪个SOCKET上发生了事件
//
// Hints: 其实有更好的改进算法,但是为了降低代码的复杂性,就留给读者去考虑了
//
///////////////////////////////////////////////////////////////////////////////////////
int GetCurrentSocketIndex(LPWSAOVERLAPPED Overlapped)
{
for(int i=0;i<nSockTotal;i++)
{
if(AcceptOverlapped[i].Internal == Overlapped->Internal) // 因为每个Overlapped结构的Internal值都是不一样的
return i;
}
return -1;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 给主窗体发消息显示文字信息
//
// Parameters: index: 标志哪个SOCKET上发生了事件
// str 要显示的信息
//
/////////////////////////////////////////////////////////////////////////////////////////
void CServerSocket::ShowMessage(const int index, const CString& str)
{
CString strSock;
strSock.Format("SOCKET编号:%d", sockArray[index] );
::SendMessage(
CServerSocket::m_hNotifyWnd,
WM_MSG_NEW_SOCKET,
(LPARAM)(LPCTSTR)strSock,
(LPARAM)(LPCTSTR)str
);
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 关闭指定SOCKET,释放资源
//
/////////////////////////////////////////////////////////////////////////////////////////
void ReleaseSocket(const int index)
{
CServerSocket::ShowMessage(index, CString("客户端断开连接!"));
closesocket(sockArray[index]); // 关闭SOCKET
sockArray[index] = INVALID_SOCKET;
nSockTotal --; // SOCKET总数减一
nCurSockIndex = NULLSOCKET;
if(nSockTotal <= 0) // 如果SOCKET总数为0,则处理线程休眠
pWaitForCompletionThread->SuspendThread();
}
////////////////////////////////////////////////////////////////////////////////////////
//
// Purposes: 获得本机IP
//
/////////////////////////////////////////////////////////////////////////////////////////
CString CServerSocket::GetLocalIP()
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)==SOCKET_ERROR)
{
AfxMessageBox("取得主机名字失败!");
return "未能获得";
}
char hostname[20];
gethostname(hostname,sizeof(hostname)); // 获得本机主机名
struct hostent FAR* lpHostEnt = gethostbyname(hostname);
if(lpHostEnt == NULL)
{
return "0.0.0.0";
}
LPSTR lpAddr = lpHostEnt->h_addr_list[0]; // 取得IP地址列表中的第一个为返回的IP
struct in_addr inAddr;
memmove(&inAddr,lpAddr,4);
return inet_ntoa(inAddr); // 转化成标准的IP地址形式
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -