Socket启用消息模式后,不能响应Socket消息,请高手指点

时空隧道 2006-08-18 03:42:25
我在Socket的服务器端使用消息模式后,客户端也同样使用消息模式,并用同一个socket实列不断去连接服务器,服务器端能响应开始的OnAccept()事件,但之后却再也没有反应,客户端在连接之前会关闭再连,我跟踪了一下,如果将客户端的连接频率降低到服务器每一次响应Accept事件的时间,那么每一次却能正常连接且成功,但如果服务器在响应过程中客户端断开连接,那么服务器在这一次的Accept会成功,但之后却再也不会对仍何Socket事件响应,请问各位高手这时怎么会事呀。
...全文
242 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
时空隧道 2006-08-18
  • 打赏
  • 举报
回复
服务器端初始化代码代码

BOOL CTestServerDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
m_socketServer.SocketInit();

m_socketServer.Create(8726);
m_socketServer.Bind(8726,"192.168.0.119");
m_socketServer.Listen();
// TODO: Add extra initialization here

return TRUE; // return TRUE unless you set the focus to a control
}
时空隧道 2006-08-18
  • 打赏
  • 举报
回复

//************************************************************************************
//sConnectedSocket:响应连接请求的目的Socket对象
//lpSockAddr:挷定到的目的地址
//说明:响应连接请求
//************************************************************************************
BOOL CAsyncSocketEx::Accept(CAsyncSocketEx& sConnectedSocket, sockaddr_in* lpSockAddr)
{
sockaddr_in adrTmp;
int nAdrSize=sizeof(sockaddr_in);
sConnectedSocket.m_hSocket=accept(m_hSocket,(sockaddr*)&adrTmp,&nAdrSize);
if(sConnectedSocket.m_hSocket==INVALID_SOCKET)
{
return FALSE;
}
if(lpSockAddr!=NULL)
{
*lpSockAddr=adrTmp;
}

char cByte;
if(sConnectedSocket.Receive(&cByte,1)==0)
{
sConnectedSocket.Close();
return FALSE;
}


if(!sConnectedSocket.CreateSocketWnd())
return FALSE;

//设置保持活动周期必须是在2000以上才有效
BOOL b=TRUE;
::setsockopt(sConnectedSocket.m_hSocket,SOL_SOCKET,SO_KEEPALIVE,(char*)&b,sizeof(BOOL));
tcp_keepalive live,liveout;
live.keepaliveinterval=5000;
//每30秒钟检查一次
live.keepalivetime=30000;
live.onoff=TRUE;

DWORD dw;
::WSAIoctl(sConnectedSocket.m_hSocket,SIO_KEEPALIVE_VALS,&live,sizeof(live),
&liveout,sizeof(liveout),&dw,NULL,NULL);

if(!sConnectedSocket.AsyncSelect(FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE))
return FALSE;
sConnectedSocket.OnServerConnected();

return TRUE;

}

//Socket2.0库初始化
BOOL CAsyncSocketEx::SocketInit(void)
{
WSADATA wsaData;
if(::WSAStartup(MAKEWORD(2,2),&wsaData)==0)
return TRUE;
else
return FALSE;

}


//将Socket置于监听模式
BOOL CAsyncSocketEx::Listen(void)
{
if(m_hSocket==NULL)
return FALSE;
if(listen(m_hSocket, MAX_CLIENT) == SOCKET_ERROR)
{
return FALSE;
}

return TRUE;
}

//挷定到具体的端口和地址
BOOL CAsyncSocketEx::Bind( UINT nSocketPort, LPCTSTR lpszSocketAddress)
{
if(m_hSocket==NULL)
return FALSE;
sockaddr_in skAddr;
skAddr.sin_family=AF_INET;
skAddr.sin_port=htons(nSocketPort);
if(lpszSocketAddress!=NULL)
skAddr.sin_addr.S_un.S_addr=inet_addr(lpszSocketAddress);
else
skAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
if(skAddr.sin_addr.S_un.S_addr==INADDR_NONE)
{
return FALSE;
}
return Bind((sockaddr_in*)&skAddr);
}

//挷定到地址和端口号
BOOL CAsyncSocketEx::Bind (const sockaddr_in* lpSockAddr)
{
if(bind(m_hSocket,(sockaddr*)lpSockAddr,sizeof(sockaddr_in))==SOCKET_ERROR)
{
return FALSE;
}
return TRUE;
}



//在服务器端的连接成功事件
void CAsyncSocketEx::OnServerConnected(void)
{

}

//测试并读取输入缓冲区数据
int CAsyncSocketEx::TryReceive(char *lpBuf, int nSize, int nFlags)
{
int nBytesReceived=0;
try
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {0, 0};
//0毫秒读时间,还未完成,则超时
if(select(0, &fd, NULL, NULL, &tv) == 0)
{
return SOCKET_ERROR;
}

nBytesReceived=recv(m_hSocket, lpBuf, nSize, nFlags);
}
catch(...)
{

}

return nBytesReceived;
}



//取最后一次网络错误号
int CAsyncSocketEx::GetLastError(void)
{
return::WSAGetLastError();
}

//从对象中分离Socket句柄
SOCKET CAsyncSocketEx::Detach(void)
{
SOCKET s=m_hSocket;
m_hSocket=NULL;
Close();
return s;
}

//取连接对方的主机名
BOOL CAsyncSocketEx::GetPeerName(CString& rPeerAddress, UINT& rPeerPort)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));

int nSockAddrLen = sizeof(sockAddr);
BOOL bResult =::getpeername(m_hSocket,(SOCKADDR*)&sockAddr, &nSockAddrLen);
if (!bResult)
{
rPeerPort = ntohs(sockAddr.sin_port);
rPeerAddress = inet_ntoa(sockAddr.sin_addr);
return TRUE;
}
return bResult;
}

//取自身主机名
BOOL CAsyncSocketEx::GetSockName(CString& rSocketAddress, UINT& rSocketPort)
{
SOCKADDR_IN sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));

int nSockAddrLen = sizeof(sockAddr);
BOOL bResult = getsockname(m_hSocket,(SOCKADDR*)&sockAddr, &nSockAddrLen);
if (!bResult)
{
rSocketPort = ntohs(sockAddr.sin_port);
rSocketAddress = inet_ntoa(sockAddr.sin_addr);
return TRUE;
}
return bResult;
}

//Socket事件处理入口
LRESULT CALLBACK CAsyncSocketEx::SocketEventProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{

WORD wErrorCode=WSAGETSELECTERROR(lParam);
WORD wEvent=WSAGETSELECTEVENT(lParam);

if(wEvent&FD_READ)
{
OnReceive(wErrorCode);
}


if(wEvent&FD_CLOSE)
{
OnClose(wErrorCode);
}


if(wEvent&FD_WRITE)
{
OnSend(wErrorCode);
}

if(wEvent&FD_ACCEPT)
{
OnAccept(wErrorCode);
}

if(wEvent&FD_CONNECT)
{
OnConnect(wErrorCode);
}
if(wEvent&FD_OOB)
{
TRACE("OnOOB\n");
}
if(wEvent&FD_QOS)
{
TRACE("OnQOS\n");

}
if(wEvent&FD_GROUP_QOS)
{
TRACE("OnGROUP_QOS\n");

}
if(wEvent&FD_ROUTING_INTERFACE_CHANGE)
{
TRACE("OnROUTING_INTERFACE_CHANGE\n");

}
if(wEvent&FD_ADDRESS_LIST_CHANGE)
{
TRACE("OnADDRESS_LIST_CHANGE\n");

}


return 0;
}

//启用消息模式
BOOL CAsyncSocketEx::AsyncSelect(long lEvent)
{
ASSERT(m_hSocket != INVALID_SOCKET);

ASSERT(m_pSocketWnd!= NULL);

ASSERT(m_pSocketWnd->m_hWnd!=NULL);

return WSAAsyncSelect(m_hSocket, m_pSocketWnd->m_hWnd,
WM_SOCKET_NOTIFY, lEvent) != SOCKET_ERROR;

}
//创建Socket消息处理窗口
BOOL CAsyncSocketEx::CreateSocketWnd()
{
if(m_pSocketWnd==NULL)
{
m_pSocketWnd= new CSocketWnd(this);
if (!m_pSocketWnd->CreateEx( 0, AfxRegisterWndClass(0),
_T("SocketEx Notification Sink"),
WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL))
{
TRACE0("Warning: unable to create socket notify window!\n");
AfxThrowResourceException();
return FALSE;
}
}
BOOL bDebug=TRUE;

setsockopt(m_hSocket,SOL_SOCKET,SO_DEBUG,(const char*)&bDebug,sizeof(BOOL));
return TRUE;
}

//************************************************
//nSize:缓冲区大小,0为不使用系统缓冲区,直接将用户缓冲区中数据发送
//说明:设置发送缓冲区大小
//************************************************
BOOL CAsyncSocketEx::SetSendBuffSize(long nSize)
{
return setsockopt(m_hSocket,SOL_SOCKET,SO_SNDBUF,(char*)&nSize,sizeof(nSize));
}

//************************************************
//nSize:缓冲区大小,0为不使用系统缓冲区,直接将数据接收到用户缓冲区中
//说明:设置接收缓冲区大小
//************************************************
BOOL CAsyncSocketEx::SetRevBuffSize(long nSize)
{
return setsockopt(m_hSocket,SOL_SOCKET,SO_RCVBUF,(char*)&nSize,sizeof(nSize));
}

//将CAsyncSocketEx对象关连到Socket句柄
BOOL CAsyncSocketEx::Attach(SOCKET hSocket, long lEvent)
{
if(m_hSocket==INVALID_SOCKET)
return FALSE;
m_hSocket=hSocket;
if(!CreateSocketWnd())
return FALSE;
return AsyncSelect(lEvent);
}

BOOL CAsyncSocketEx::IsConnect()
{
int nTime=0xffffffff;
int nSize=sizeof(nTime);
getsockopt( m_hSocket,SOL_SOCKET,SO_CONNECT_TIME,(char*)&nTime,&nSize);
if(nTime==0xffffffff)
return FALSE;
else
return TRUE;

}


// 获取当前套接字是否可读写,参数0表示查询读状态,1表示查写状态,2表示带外数据情况
BOOL CAsyncSocketEx::Select(int nType)
{
if(nType==0)
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {0, 0};
//300秒读时间,还未完成,则超时
if(select(0, &fd, NULL, NULL, &tv) == 0)
{
//超时
return 0;
}
return TRUE;
}
else if(nType==1)
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {0, 0};
//300秒读时间,还未完成,则超时
if(select(0, NULL,&fd, NULL, &tv) == 0)
{
//超时
return 0;
}
return TRUE;
}
return 0;
}

时空隧道 2006-08-18
  • 打赏
  • 举报
回复
// AsyncSocketEx.cpp: implementation of the CAsyncSocketEx class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "AsyncSocketEx.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//定义Socket事件消息
#define WM_SOCKET_NOTIFY WM_USER+1121
//定义最大可支持客户端数量
#define MAX_CLIENT 1024
//定义用于处理Socket消息窗口
class CSocketWnd: public CWnd
{
public:
//拷贝构造
CSocketWnd(CAsyncSocketEx *pSocket)
{
m_pSocket=pSocket;
}
//析构
~CSocketWnd()
{
if(m_hWnd!=NULL)
{
DestroyWindow();
m_hWnd=NULL;
}
}

//Socket消息处理
LRESULT OnSocketEventMessage(WPARAM wParam,LPARAM lParam)
{
if(m_pSocket)
{
return m_pSocket->SocketEventProc(m_hWnd,WM_SOCKET_NOTIFY,wParam,lParam);
}
return 0;
}

/*
afx_msg void OnTimer(UINT nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值

if(nIDEvent==0)
{
KillTimer(nIDEvent);
if(m_pSocket)
{
if(m_pSocket->Select(0))
m_pSocket->OnAccept(0);

}

}
CWnd::OnTimer(nIDEvent);
}
*/


private:
CAsyncSocketEx* m_pSocket;
protected:
DECLARE_MESSAGE_MAP()

public:
};

BEGIN_MESSAGE_MAP(CSocketWnd, CWnd)
//{{AFX_MSG_MAP(CAboutDlg)
ON_MESSAGE(WM_SOCKET_NOTIFY,OnSocketEventMessage)
// ON_WM_TIMER()
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


///////////////




CAsyncSocketEx::CAsyncSocketEx()
{
m_hSocket=NULL;
m_pSocketWnd=NULL;
}

CAsyncSocketEx::~CAsyncSocketEx()
{
if(m_pSocketWnd!=NULL)
{

delete m_pSocketWnd;
m_pSocketWnd=NULL;
}

if(m_hSocket)
{
Close();
m_hSocket=NULL;
}

}


#include "AsyncSocketEx.h"
#include "mstcpip.h"
#include "mmsystem.h"




//**************************************//
//nPort: 需要邦定的端口号,缺省为0->自动邦定
//返 回:无
//说 明:创建socket
//**************************************//
BOOL CAsyncSocketEx::Create( UINT nSocketPort,int nSocketType, long lEvent, LPCTSTR lpszSocketAddress)
{
Close();

if(m_hSocket!=NULL)
{
return FALSE;
}
//流式协议
if((m_hSocket = socket(AF_INET,nSocketType, 0)) == INVALID_SOCKET)
{
return FALSE;
}
//设置保持活动周期必须是在2000以下才有效
BOOL b=TRUE;
::setsockopt(m_hSocket,SOL_SOCKET,SO_KEEPALIVE,(char*)&b,sizeof(BOOL));
tcp_keepalive live,liveout;
//保持包传输时间
live.keepaliveinterval=5000;
//每30秒钟检查一次
live.keepalivetime=30000;
live.onoff=TRUE;

DWORD dw;
::WSAIoctl(m_hSocket,SIO_KEEPALIVE_VALS,&live,sizeof(live),
&liveout,sizeof(liveout),&dw,NULL,NULL);
if(nSocketPort>0)
Bind(nSocketPort);

if(!CreateSocketWnd())
return FALSE;

return AsyncSelect(lEvent);
}

//错误处理入口
void CAsyncSocketEx::OnError(int nErrorCode)
{
}

//关闭事件处理
void CAsyncSocketEx::OnClose(int nErrorCode)
{
Close();
}

//数据到达通知入口
void CAsyncSocketEx::OnReceive(int nErrorCode)
{


}
//可发送数据通知入口
void CAsyncSocketEx::OnSend(int nErrorCode)
{


}
//连接请求入口
void CAsyncSocketEx::OnAccept(int nErrorCode)
{


}
//************************************************
//nErrorCode:非零表示连接成功,否则表示有错误发生
//说明:客户端连接结果通知
//************************************************
void CAsyncSocketEx::OnConnect(int nErrorCode)
{

}
//************************************************************
//lpBuf:接收缓冲区
//nSize:接收缓冲区大小
//nFlags:接收方式,0表示接收后清除系统接收缓冲区,
// MSG_PEEK为接收后不清除系统接收缓冲区
//说明:接收数据
//************************************************************
int CAsyncSocketEx::Receive(char *lpBuf, int nSize, int nFlags)
{

int nBytesReceived=0;
try
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {300, 0};
//300秒读时间,还未完成,则超时
if(select(0, &fd, NULL, NULL, &tv) == 0)
{
//超时
return SOCKET_ERROR;
}
if((nBytesReceived = recv(m_hSocket, lpBuf, nSize, nFlags)) == SOCKET_ERROR)
{
return SOCKET_ERROR;
}
}
catch(...)
{
return SOCKET_ERROR;
}
return nBytesReceived;
}


//执行关闭(断开连接)
BOOL CAsyncSocketEx::Close(void)
{
try
{

if(m_hSocket!=NULL)
{
try
{
BOOL b=TRUE;
::setsockopt(m_hSocket,SOL_SOCKET,SO_DONTLINGER,(char*)&b,sizeof(b));
shutdown(m_hSocket,SD_BOTH);
}
catch(...)
{
}

try
{
closesocket(m_hSocket);
}
catch(...)
{
}
m_hSocket=NULL;
}


//释放窗口资源
if(m_pSocketWnd!=NULL)
{
delete m_pSocketWnd;
m_pSocketWnd=NULL;
}


}
catch(...)
{

}
m_hSocket = NULL;
return TRUE;
}

//*********************************************************
//lpBuf:发送缓冲区
//nSize:发送缓区长度
//nFlags:发送标志,一般情况为0,MSG_OOB为带外发送
//说明:发送数据
//*********************************************************
int CAsyncSocketEx::Send(char* lpBuf, int nSize, int nFlags)
{


int nBytesSent=0;
try
{

if(m_hSocket == NULL)
{
return 0;
}

FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {300, 0};
if(select(0, NULL,&fd, NULL, &tv) == 0)
{//超时
return SOCKET_ERROR;
}

if((nBytesSent = send(m_hSocket, lpBuf, nSize, 0)) == SOCKET_ERROR)
{
TRACE("exit Send(char* lpBuf, int nSize, int nFlags)\n");
return SOCKET_ERROR;
}
}
catch(...)
{
return SOCKET_ERROR;
}

TRACE("exit Send(char* lpBuf, int nSize, int nFlags)\n");
return nBytesSent;
}

//********************************************************************
//lpszHostAddress:主机地址
//nHostPort:主机监听端口号
//说明:建立连接与主机之间的连接
//********************************************************************
BOOL CAsyncSocketEx::Connect( LPCTSTR lpszHostAddress, UINT nHostPort )
{
if(m_hSocket==NULL)
return FALSE;
sockaddr_in skAddr;
::ZeroMemory(&skAddr,sizeof(skAddr));
skAddr.sin_family=AF_INET;
skAddr.sin_port=htons(nHostPort);
skAddr.sin_addr.S_un.S_addr=inet_addr(lpszHostAddress);
if(skAddr.sin_addr.S_un.S_addr==INADDR_NONE)
{
hostent *host;
host=::gethostbyname(lpszHostAddress);
if(host==NULL)
return FALSE;
CopyMemory(&skAddr.sin_addr,host->h_addr_list[0],host->h_length);
}

BOOL bConditionalAccept=TRUE;

setsockopt(m_hSocket,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));

return Connect(&skAddr);
}

//建立到主机之间的连接,只供类内部提供调用
BOOL CAsyncSocketEx::Connect( const sockaddr_in* lpSockAddr)
{
if(connect(m_hSocket,(sockaddr*)lpSockAddr,sizeof(sockaddr_in))==SOCKET_ERROR)
{
return FALSE;
}

return TRUE;
}

VOID TimerProc1(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime)
{
INT S=0;
return ;
}
Elysium 2006-08-18
  • 打赏
  • 举报
回复
用的没有问题啊,UDP?TCP?
SOCKET API?还是CSocket
yangsky971 2006-08-18
  • 打赏
  • 举报
回复
客户端会做关闭,服务器端有没有做关闭,否则它还是在原来的信道上。
肯定是你的代码哪里有问题,放出来再说吧,或者你自己再仔细检查下,有例子的仔细对下例子,看自己到底那里差那么一点点。祝好。。。
jerry 2006-08-18
  • 打赏
  • 举报
回复
可能是你的accept处理有问题.

你最好把服务器代码帖出来看看

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧