在视图类中启动建立服务器端Socket线程,然后在服务器线程中接收连接,建立客户处理线程.客户处理线程解析报文并做相应的处理.
现在的问题是,客户处理线程一接收数据,程序就甭掉了,郁闷ing,还请大侠救我!
全局变量和包文头定义:
//define global variables.
UINT g_nPortServer = 3313;
int g_nConnection = 0;
BOOL g_bListening = FALSE;
CBlockingSocket g_sListen;#define MAXBUF 2048
typedef ::std::vector<CBlockingSocket *> SocketVector;
SocketVector g_vClientSocket; typedef struct _MsgHead //消息头
{
WORD wVersion; //版本信息
WORD wFlag; //消息标志
WORD wType; //消息类别
WORD wMsgLen; //消息长度
} MsgHead;视图类
void CBookServerView::OnServeStart()
{
char szErrMsg[255];
try
{
CSockAddr saServer = CSockAddr(INADDR_ANY, (USHORT)g_nPortServer);
g_sListen.Create();
g_sListen.Bind(saServer);
g_sListen.Listen();// start listening
g_bListening = TRUE;
g_nConnection = 0;
AfxBeginThread(ServerThreadProc, GetSafeHwnd(), THREAD_PRIORITY_NORMAL);
}
catch(CBlockingSocketException* e)
{
g_sListen.Cleanup();
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}//服务器线程
UINT ServerThreadProc(LPVOID pParam)
{
char szErrMsg[255];
CSockAddr saClient;
CBlockingSocket sClient;
while (1)
{
try
{
CString s;
s.Format("%d", sizeof(LPSOCKADDR));
AfxMessageBox(s);
s.Format("%d", sizeof(saClient));
AfxMessageBox(s);
if (!g_sListen.Accept(sClient, (LPSOCKADDR)&saClient))
{
// view or application closed the listing socket
g_bListening = FALSE;
}
else
{
g_nConnection++;
AfxBeginThread(ClientThreadProc, (LPVOID)&sClient, THREAD_PRIORITY_NORMAL);
}
}
catch (CBlockingSocketException* e)
{
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}
return 0;
} /*end of proc*///用户线程
UINT ClientThreadProc(LPVOID pParam)
{
CBlockingSocket * psClient = (CBlockingSocket *)pParam;
char szErrMsg[255];
while(1)
{
try {
// Perform a blocking recv() call
//
char szMsgHead[255];
//memset((void *)szMsgHead, 0, sizeof(MsgHead));
int nBytesRcv = psClient->Receive((char *)szMsgHead, sizeof(MsgHead), 65535); //经过调试发现一到这里就出错了。
// Graceful close
if (0 == nBytesRcv)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
break;
}
else if (sizeof(MsgHead) != nBytesRcv)
{
continue;
} MsgHead *pMsgHead = (MsgHead *)szMsgHead;
//check the correctness of packet.
if (pMsgHead->wVersion >= 100 && pMsgHead->wVersion <= 1000 && pMsgHead->wFlag == sizeof(MsgHead))
{
char* szBuffer = new char[pMsgHead->wMsgLen + 1];
memset(szBuffer, 1, pMsgHead->wMsgLen + 1);
nBytesRcv = psClient->Receive((char *)szBuffer, sizeof(pMsgHead->wMsgLen + 1), 1);
if (0 == nBytesRcv)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
break;
}
else if (sizeof(MsgHead) != nBytesRcv)
{
continue;
}
if (100 == pMsgHead->wVersion)
{
switch (pMsgHead->wType)
{
case 1 :
{ //User Login
CSockAddr sPeerAddr;
psClient->GetPeerAddr((SOCKADDR *)&sPeerAddr);
CMainFrame *pMainFrame =(CMainFrame *)AfxGetMainWnd();
CBookServerView *pMainView = (CBookServerView *)(pMainFrame->GetActiveView());
char *szUserName = szBuffer;
char *szPassword = szBuffer + strlen(szUserName) + 1;
CListCtrl & wndListCtrl = pMainView->GetListCtrl();
int nItemCnt = wndListCtrl.GetItemCount();
wndListCtrl.InsertItem(nItemCnt, "NEWUSER"); wndListCtrl.SetItemText(nItemCnt, 0, sPeerAddr.DottedDecimal());
wndListCtrl.SetItemText(nItemCnt, 1, (const char *)ultoa(sPeerAddr.Port(), (char *)szErrMsg, 10));
wndListCtrl.SetItemText(nItemCnt, 2, (const char *)szUserName);
break;
}
case 2 :
{
break;
}
case 3 :
{
break;
}
default:
{
}
}
} delete []szBuffer;
}
}
catch (CBlockingSocketException* e)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}
return 0;
}
现在的问题是,客户处理线程一接收数据,程序就甭掉了,郁闷ing,还请大侠救我!
全局变量和包文头定义:
//define global variables.
UINT g_nPortServer = 3313;
int g_nConnection = 0;
BOOL g_bListening = FALSE;
CBlockingSocket g_sListen;#define MAXBUF 2048
typedef ::std::vector<CBlockingSocket *> SocketVector;
SocketVector g_vClientSocket; typedef struct _MsgHead //消息头
{
WORD wVersion; //版本信息
WORD wFlag; //消息标志
WORD wType; //消息类别
WORD wMsgLen; //消息长度
} MsgHead;视图类
void CBookServerView::OnServeStart()
{
char szErrMsg[255];
try
{
CSockAddr saServer = CSockAddr(INADDR_ANY, (USHORT)g_nPortServer);
g_sListen.Create();
g_sListen.Bind(saServer);
g_sListen.Listen();// start listening
g_bListening = TRUE;
g_nConnection = 0;
AfxBeginThread(ServerThreadProc, GetSafeHwnd(), THREAD_PRIORITY_NORMAL);
}
catch(CBlockingSocketException* e)
{
g_sListen.Cleanup();
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}//服务器线程
UINT ServerThreadProc(LPVOID pParam)
{
char szErrMsg[255];
CSockAddr saClient;
CBlockingSocket sClient;
while (1)
{
try
{
CString s;
s.Format("%d", sizeof(LPSOCKADDR));
AfxMessageBox(s);
s.Format("%d", sizeof(saClient));
AfxMessageBox(s);
if (!g_sListen.Accept(sClient, (LPSOCKADDR)&saClient))
{
// view or application closed the listing socket
g_bListening = FALSE;
}
else
{
g_nConnection++;
AfxBeginThread(ClientThreadProc, (LPVOID)&sClient, THREAD_PRIORITY_NORMAL);
}
}
catch (CBlockingSocketException* e)
{
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}
return 0;
} /*end of proc*///用户线程
UINT ClientThreadProc(LPVOID pParam)
{
CBlockingSocket * psClient = (CBlockingSocket *)pParam;
char szErrMsg[255];
while(1)
{
try {
// Perform a blocking recv() call
//
char szMsgHead[255];
//memset((void *)szMsgHead, 0, sizeof(MsgHead));
int nBytesRcv = psClient->Receive((char *)szMsgHead, sizeof(MsgHead), 65535); //经过调试发现一到这里就出错了。
// Graceful close
if (0 == nBytesRcv)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
break;
}
else if (sizeof(MsgHead) != nBytesRcv)
{
continue;
} MsgHead *pMsgHead = (MsgHead *)szMsgHead;
//check the correctness of packet.
if (pMsgHead->wVersion >= 100 && pMsgHead->wVersion <= 1000 && pMsgHead->wFlag == sizeof(MsgHead))
{
char* szBuffer = new char[pMsgHead->wMsgLen + 1];
memset(szBuffer, 1, pMsgHead->wMsgLen + 1);
nBytesRcv = psClient->Receive((char *)szBuffer, sizeof(pMsgHead->wMsgLen + 1), 1);
if (0 == nBytesRcv)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
break;
}
else if (sizeof(MsgHead) != nBytesRcv)
{
continue;
}
if (100 == pMsgHead->wVersion)
{
switch (pMsgHead->wType)
{
case 1 :
{ //User Login
CSockAddr sPeerAddr;
psClient->GetPeerAddr((SOCKADDR *)&sPeerAddr);
CMainFrame *pMainFrame =(CMainFrame *)AfxGetMainWnd();
CBookServerView *pMainView = (CBookServerView *)(pMainFrame->GetActiveView());
char *szUserName = szBuffer;
char *szPassword = szBuffer + strlen(szUserName) + 1;
CListCtrl & wndListCtrl = pMainView->GetListCtrl();
int nItemCnt = wndListCtrl.GetItemCount();
wndListCtrl.InsertItem(nItemCnt, "NEWUSER"); wndListCtrl.SetItemText(nItemCnt, 0, sPeerAddr.DottedDecimal());
wndListCtrl.SetItemText(nItemCnt, 1, (const char *)ultoa(sPeerAddr.Port(), (char *)szErrMsg, 10));
wndListCtrl.SetItemText(nItemCnt, 2, (const char *)szUserName);
break;
}
case 2 :
{
break;
}
case 3 :
{
break;
}
default:
{
}
}
} delete []szBuffer;
}
}
catch (CBlockingSocketException* e)
{
//管理Socket
for (SocketVector::iterator itv = g_vClientSocket.begin(); itv != g_vClientSocket.end(); ++itv)
{
if (psClient == *itv)
{
g_vClientSocket.erase(itv);
}
}
//g_vClientSocket
g_nConnection --;
e->GetErrorMessage(szErrMsg, 255);
ErrMsgOutput(szErrMsg);
e->Delete();
}
}
return 0;
}
{
DECLARE_DYNAMIC(CBlockingSocketException)
public:
// Constructor
CBlockingSocketException(char* pchMessage);public:
~CBlockingSocketException() {}
virtual BOOL GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
PUINT pnHelpContext = NULL);
private:
int m_nError;
CString m_strMessage;
};
class CSockAddr : public sockaddr_in {
public:
// constructors
CSockAddr()
{ sin_family = AF_INET;
sin_port = 0;
sin_addr.s_addr = 0; } // Default
CSockAddr(const SOCKADDR& sa) { memcpy(this, &sa, sizeof(SOCKADDR)); }
CSockAddr(const SOCKADDR_IN& sin) { memcpy(this, &sin, sizeof(SOCKADDR_IN)); }
CSockAddr(const ULONG ulAddr, const USHORT ushPort = 0) // parms are host byte ordered
{ sin_family = AF_INET;
sin_port = htons(ushPort);
sin_addr.s_addr = htonl(ulAddr); }
CSockAddr(const char* pchIP, const USHORT ushPort = 0) // dotted IP addr string
{ sin_family = AF_INET;
sin_port = htons(ushPort);
sin_addr.s_addr = inet_addr(pchIP); } // already network byte ordered
// Return the address in dotted-decimal format
CString DottedDecimal()
{ return inet_ntoa(sin_addr); } // constructs a new CString object
// Get port and address (even though they're public)
USHORT Port() const
{ return ntohs(sin_port); }
ULONG IPAddr() const
{ return ntohl(sin_addr.s_addr); }
// operators added for efficiency
const CSockAddr& operator=(const SOCKADDR& sa)
{ memcpy(this, &sa, sizeof(SOCKADDR));
return *this; }
const CSockAddr& operator=(const SOCKADDR_IN& sin)
{ memcpy(this, &sin, sizeof(SOCKADDR_IN));
return *this; }
operator SOCKADDR()
{ return *((LPSOCKADDR) this); }
operator LPSOCKADDR()
{ return (LPSOCKADDR) this; }
operator LPSOCKADDR_IN()
{ return (LPSOCKADDR_IN) this; }
};// member functions truly block and must not be used in UI threads
// use this class as an alternative to the MFC CSocket class
class CBlockingSocket : public CObject
{
DECLARE_DYNAMIC(CBlockingSocket)
public:
SOCKET m_hSocket;
CBlockingSocket() { m_hSocket = NULL; }
void Cleanup();
void Create(int nType = SOCK_STREAM);
void Close();
void Bind(LPCSOCKADDR psa);
void Listen();
void Connect(LPCSOCKADDR psa);
BOOL Accept(CBlockingSocket& s, LPSOCKADDR psa);
int Send(const char* pch, const int nSize, const int nSecs);
int Write(const char* pch, const int nSize, const int nSecs);
int Receive(char* pch, const int nSize, const int nSecs);
int SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa,
const int nSecs);
int ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa,
const int nSecs);
void GetPeerAddr(LPSOCKADDR psa);
void GetSockAddr(LPSOCKADDR psa);
static CSockAddr GetHostByName(const char* pchName,
const USHORT ushPort = 0);
static const char* GetHostByAddr(LPCSOCKADDR psa);
operator SOCKET()
{ return m_hSocket; }
};
#include "stdafx.h"
#include "blocksock.h"// Class CBlockingSocketException
IMPLEMENT_DYNAMIC(CBlockingSocketException, CException)CBlockingSocketException::CBlockingSocketException(char* pchMessage)
{
m_strMessage = pchMessage;
m_nError = WSAGetLastError();
}BOOL CBlockingSocketException::GetErrorMessage(LPTSTR lpstrError, UINT nMaxError,
PUINT pnHelpContext /*= NULL*/)
{ char text[200];
if(m_nError == 0) {
wsprintf(text, "%s error", (const char*) m_strMessage);
}
else {
wsprintf(text, "%s error #%d", (const char*) m_strMessage, m_nError);
}
strncpy(lpstrError, text, nMaxError - 1);
return TRUE;
}// Class CBlockingSocket
IMPLEMENT_DYNAMIC(CBlockingSocket, CObject)void CBlockingSocket::Cleanup()
{
// doesn't throw an exception because it's called in a catch block
if(m_hSocket == NULL) return;
VERIFY(closesocket(m_hSocket) != SOCKET_ERROR);
m_hSocket = NULL;
}void CBlockingSocket::Create(int nType /* = SOCK_STREAM */)
{
ASSERT(m_hSocket == NULL);
if((m_hSocket = socket(AF_INET, nType, 0)) == INVALID_SOCKET) {
throw new CBlockingSocketException("Create");
}
}void CBlockingSocket::Bind(LPCSOCKADDR psa)
{
ASSERT(m_hSocket != NULL);
if(bind(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
throw new CBlockingSocketException("Bind");
}
}void CBlockingSocket::Listen()
{
ASSERT(m_hSocket != NULL);
if(listen(m_hSocket, 5) == SOCKET_ERROR) {
throw new CBlockingSocketException("Listen");
}
}BOOL CBlockingSocket::Accept(CBlockingSocket& sConnect, LPSOCKADDR psa)
{
ASSERT(m_hSocket != NULL);
ASSERT(sConnect.m_hSocket == NULL);
int nLengthAddr = sizeof(SOCKADDR);
sConnect.m_hSocket = accept(m_hSocket, psa, &nLengthAddr);
if(sConnect == INVALID_SOCKET) {
// no exception if the listen was canceled
if(WSAGetLastError() != WSAEINTR) {
throw new CBlockingSocketException("Accept");
}
return FALSE;
}
return TRUE;
}void CBlockingSocket::Close()
{
ASSERT(m_hSocket != NULL);
if(closesocket(m_hSocket) == SOCKET_ERROR) {
// should be OK to close if closed already
throw new CBlockingSocketException("Close");
}
m_hSocket = NULL;
}void CBlockingSocket::Connect(LPCSOCKADDR psa)
{
ASSERT(m_hSocket != NULL);
// should timeout by itself
if(connect(m_hSocket, psa, sizeof(SOCKADDR)) == SOCKET_ERROR) {
throw new CBlockingSocketException("Connect");
}
}int CBlockingSocket::Write(const char* pch, const int nSize, const int nSecs)
{
int nBytesSent = 0;
int nBytesThisTime;
const char* pch1 = pch;
do {
nBytesThisTime = Send(pch1, nSize - nBytesSent, nSecs);
nBytesSent += nBytesThisTime;
pch1 += nBytesThisTime;
} while(nBytesSent < nSize);
return nBytesSent;
}int CBlockingSocket::Send(const char* pch, const int nSize, const int nSecs)
{
ASSERT(m_hSocket != NULL);
// returned value will be less than nSize if client cancels the reading
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {nSecs, 0};
if(select(0, NULL, &fd, NULL, &tv) == 0) {
throw new CBlockingSocketException("Send timeout");
}
int nBytesSent;
if((nBytesSent = send(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
throw new CBlockingSocketException("Send");
}
return nBytesSent;
}int CBlockingSocket::Receive(char* pch, const int nSize, const int nSecs)
{
// ASSERT(m_hSocket != NULL);
// FD_SET fd = {1, m_hSocket};
// TIMEVAL tv = {nSecs, 0};
// if(select(0, &fd, NULL, NULL, &tv) == 0) {
// throw new CBlockingSocketException("Receive timeout");
// } int nBytesReceived;
if((nBytesReceived = recv(m_hSocket, pch, nSize, 0)) == SOCKET_ERROR) {
throw new CBlockingSocketException("Receive");
}
return nBytesReceived;
}int CBlockingSocket::ReceiveDatagram(char* pch, const int nSize, LPSOCKADDR psa, const int nSecs)
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {nSecs, 0};
if(select(0, &fd, NULL, NULL, &tv) == 0) {
throw new CBlockingSocketException("Receive timeout");
} // input buffer should be big enough for the entire datagram
int nFromSize = sizeof(SOCKADDR);
int nBytesReceived = recvfrom(m_hSocket, pch, nSize, 0, psa, &nFromSize);
if(nBytesReceived == SOCKET_ERROR) {
throw new CBlockingSocketException("ReceiveDatagram");
}
return nBytesReceived;
}int CBlockingSocket::SendDatagram(const char* pch, const int nSize, LPCSOCKADDR psa, const int nSecs)
{
ASSERT(m_hSocket != NULL);
FD_SET fd = {1, m_hSocket};
TIMEVAL tv = {nSecs, 0};
if(select(0, NULL, &fd, NULL, &tv) == 0) {
throw new CBlockingSocketException("Send timeout");
} int nBytesSent = sendto(m_hSocket, pch, nSize, 0, psa, sizeof(SOCKADDR));
if(nBytesSent == SOCKET_ERROR) {
throw new CBlockingSocketException("SendDatagram");
}
return nBytesSent;
}void CBlockingSocket::GetPeerAddr(LPSOCKADDR psa)
{
ASSERT(m_hSocket != NULL);
// gets the address of the socket at the other end
int nLengthAddr = sizeof(SOCKADDR);
if(getpeername(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
throw new CBlockingSocketException("GetPeerName");
}
}void CBlockingSocket::GetSockAddr(LPSOCKADDR psa)
{
ASSERT(m_hSocket != NULL);
// gets the address of the socket at this end
int nLengthAddr = sizeof(SOCKADDR);
if(getsockname(m_hSocket, psa, &nLengthAddr) == SOCKET_ERROR) {
throw new CBlockingSocketException("GetSockName");
}
}//static
CSockAddr CBlockingSocket::GetHostByName(const char* pchName, const USHORT ushPort /* = 0 */)
{
hostent* pHostEnt = gethostbyname(pchName);
if(pHostEnt == NULL) {
throw new CBlockingSocketException("GetHostByName");
}
ULONG* pulAddr = (ULONG*) pHostEnt->h_addr_list[0];
SOCKADDR_IN sockTemp;
sockTemp.sin_family = AF_INET;
sockTemp.sin_port = htons(ushPort);
sockTemp.sin_addr.s_addr = *pulAddr; // address is already in network byte order
return sockTemp;
}//static
const char* CBlockingSocket::GetHostByAddr(LPCSOCKADDR psa)
{
hostent* pHostEnt = gethostbyaddr((char*) &((LPSOCKADDR_IN) psa)
->sin_addr.s_addr, 4, PF_INET);
if(pHostEnt == NULL) {
throw new CBlockingSocketException("GetHostByAddr");
}
return pHostEnt->h_name; // caller shouldn't delete this memory
}