CNetTcpLsn是CAsyncSocket的一个派生类,服务端接收客户端连接,同时要把数据发给连接的客户端,客户的socket保存在m_ClientSockList里,当发送函数里调用Num = pSock->Send(_buf,nLen,0) 失败时,想立即把客户端的socket Close并删掉,但是一close就会崩溃,原因是close内部的KillSocket里断言失败,如何才能实现Send失败时,立马释放代表客户端的socket
void CNetTcpLsn::OnAccept(int nErrorCode)
{
if (nErrorCode == 0)
{
CNetAcpSock* pSock = new CNetAcpSock(m_pBase) ;
if (Accept(*pSock))
{
pSock->AsyncSelect(FD_READ|FD_CONNECT|FD_CLOSE|FD_OOB) ;
pSock->m_bConnect = TRUE;
m_ClientSockList.push_back(pSock);
m_bConnect = TRUE ; //连接标志
SOCKADDR clientAddr;
int iLength = sizeof(sockaddr);
if(pSock->GetPeerName((struct sockaddr * )&clientAddr, &iLength))
{
sockaddr_in * pSin = (sockaddr_in *)&clientAddr;
m_pBase->m_ConAddr.Format("%s:%d",inet_ntoa(pSin->sin_addr),ntohs(pSin->sin_port));
}else
m_pBase->m_ConAddr = "0.0.0.0:0";
}
else
{
delete pSock ;
pSock = NULL ;
}
}
CAsyncSocket::OnAccept(nErrorCode);
}
//发送函数
int CNetTcpLsn::_Send(char _buf, int nLen)
{
int Num = 0 ;
vector<CNetAcpSock>::iterator iter;
for (iter=m_ClientSockList.begin();iter!=m_ClientSockList.end();++iter)
{
CNetAcpSock* pSock = (CNetAcpSock*) *iter;
if (pSock)
{
Num = pSock->Send(_buf,nLen,0) ;
if (Num == SOCKET_ERROR)
{
int ret = GetLastError() ;
if( ret != 10035)
{
if (pSock->m_bConnect)
{
pSock->m_bConnect = FALSE ;//连接中断
}
}
}
else
{
if (!m_bConnect)
{
pSock->m_bConnect = TRUE;
}
}
}
}
return Num ;
}
void PASCAL CAsyncSocket::KillSocket(SOCKET hSocket, CAsyncSocket* pSocket)
{
// assert会失败CAsyncSocket::LookupHandle(hSocket, FALSE)返回是NULL
ASSERT(CAsyncSocket::LookupHandle(hSocket, FALSE) != NULL);
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
CAsyncSocket::DetachHandle(hSocket, FALSE);
if (pState->m_hSocketWindow != NULL)
{
::PostMessage(pState->m_hSocketWindow, WM_SOCKET_DEAD,
(WPARAM)hSocket, 0L);
CAsyncSocket::AttachHandle(hSocket, pSocket, TRUE);
}
}