在视图类中启动建立服务器端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;
}

解决方案 »

  1.   

    // blocksock.h// needs winsock.h in the precompiled headerstypedef const struct sockaddr* LPCSOCKADDR;class CBlockingSocketException : public CException
    {
    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; }
    };
      

  2.   

    // blocksock.cpp (CBlockingSocketException, CBlockingSocket, CHttpBlockingSocket)
    #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
    }