c/sc中的socket关闭了。s中还是FD_ISSET()还是为真,readfds: If listen has been called and a connection is pending, accept will succeed. Data is available for reading (includes OOB data if SO_OOBINLINE is enabled). Connection has been closed/reset/terminated. 这三种情况怎么区分呢?
Data is available for reading (includes OOB data if SO_OOBINLINE is enabled).
Connection has been closed/reset/terminated. 这三种情况怎么区分呢?
我也知道 recv 一下可以判断,int nRecv = recv()
if(nRecv == 0)
{
//没有可读的数据
}但是,我不相信 Select 模型会是这样的啊。
我开了一个线程专门的 select ,
select 到了FD_ISSET()为真,就发送可读消息。现在的问题是,c 端的 socket 已经关闭了,但FD_ISSET()还是为真。
所以我的线程还是不段的 发送消息。结果是可以想象的,阻塞了。我现在要在 select 线程中就判断出来 是不是可读?你有办法吗?
看看《windows 网络编程技术》第8章
是一样的啊。我感觉书上的当 socket(c端)关闭后,FD_ISSET()还是为真。
所以我想问问实际是怎么用的。不过我的问题基本解决了。
DWORD WINAPI SelectThread(LPVOID lpvoid)
{
while(true)
{
DWORD word = ::WaitForSingleObject(::g_handle, 0);
if(word == WAIT_OBJECT_0)
{
#ifdef _DEBUG
::MessageBox(NULL, "结束 Select Thread!", "Message Box",
MB_OK);
#endif
return 1;
} if(socket != 0)
{
FD_ZERO(&readfds);
FD_SET(socket, &readfds);
n = ::select(0, &readfds, NULL, NULL, &Timeval);
if(n == SOCKET_ERROR)
{
#ifdef _DEBUG
::MessageBox(NULL, "Select fail !", "Messsage Box", MB_OK);
#endif
return 0;
}
if(n > 0)
{
if(FD_ISSET(socket, &readfds))
{
//{{可读, 发送消息 UM_READABILITY
CChat_ServerApp * pwnd = (CChat_ServerApp *)::AfxGetApp();
#if 1
::SendMessage(pwnd->m_pMainWnd->m_hWnd,UM_READABILITY,
(WPARAM)pSocket, NULL);
#else
::PostMessage(pwnd->m_pMainWnd->m_hWnd,UM_READABILITY,
(WPARAM)pSocket, NULL);
#endif
//}}可读, 发送消息 UM_READABILITY
}
}
}
}//主线程
int nReceive = recv();
if(nReceive == 0)
{
::SetEvent(g_handle);
return ;
}
那么一方断开了连接,另一方是可以收到消息的,从而知道连接断了。
BOOL bConnDropped = FALSE;
INT iRet = 0;
BOOL bOK = TRUE;
struct timeval timeout = { 0, 0 };
fd_set readSocketSet;
FD_ZERO( &readSocketSet );
FD_SET( m_hSocket, &readSocketSet );
iRet = ::select( 0, &readSocketSet, NULL, NULL, &timeout );
bOK = (iRet > 0);
if(bOK){
bOK = FD_ISSET( m_hSocket, &readSocketSet );
}
if( bOK ){
CHAR szBuffer[1] = "";
iRet = ::recv( m_hSocket, szBuffer, 1, MSG_PEEK );
bOK = ( iRet > 0 );
if( !bOK ){
INT iError = ::WSAGetLastError();
bConnDropped = ( ( iError == WSAENETRESET ) ||
( iError == WSAECONNABORTED ) ||
( iError == WSAECONNRESET ) ||
( iError == WSAEINVAL ) ||
( iRet == 0 ) ); //Graceful disconnect from other side.
}
}
iRet=receive(...MSG_PEEK)先偷看一下是否有数据来,如果没有数据来,则认为断线了,反之是有数据到来的消息
郁闷,我也是暂时是这样解决的。我觉得有更好的方法。继续搜索。
目前我所做的一个小玩意里我用到了 select 模型,
其他的几种模型效率要高,《Windows 网络编程技术》中有讲。其实在我初步的看来,就思想上理解来讲,(我说我个人的观点,不对的地方请指正)
:我个人认为,我也试图把 select 模型 转变为 重叠IO 模型的,
看了一下,我觉得在思想上,我比较快的理解了(很肤浅的理解了)重叠IO模型,我觉得几种模型在思想上比较接近(个人观点),虽然实现各有各的不同。效率也不一样(书上说的,没有实际测试)。