现在可以实现同步方式,
但是一端掉线,另外一端没有接收到相关消息;
并且在recv的时候会一直阻塞;想通过Select方式实现非阻塞,并且一端掉线后,
另外一端可以及时收到相关消息,作出断开SOCKET等相关操作;请熟悉的朋友帮忙介绍下,谢谢

解决方案 »

  1.   

    //服务端代码 TCP协议// mySocketManager.h: 
    // 封装SOCKET操作类的头文件 #pragma   comment(lib,"ws2_32.lib") #pragma pack(1)extern BOOL myInitSocket(); //初始化Socket相关的库
    extern BOOL myBindSocket(SOCKET &sListen,int iPort);
    extern int  mySendDataToCli(SOCKET sockClient,char *msgToClient);
    extern BOOL myLoop(int iFlag);#pragma pack()
    /////////////////////////////////////////////////////// mySocketManager.cpp:
    // 封装SOCKET操作
    //////////////////////////////////////////////////////////////////////#include "stdafx.h"
    #include "myMFCServer.h"
    #include "mySocketManager.h"//初始化SOCKET相关的库
    BOOL myInitSocket() 
    {
        WSADATA  wsadata; 
        if(WSAStartup(MAKEWORD(2,2),&wsadata)) 
        {
            return FALSE;
        }
        
        return TRUE;
    }//绑定Socket,并启动监听
    BOOL myBindSocket(SOCKET &sListen,int iPort)
    {
        SOCKET serverListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        
        if (INVALID_SOCKET == serverListen)
        {
            return FALSE;    
        }
        
        SOCKADDR_IN sin;
        sin.sin_family = AF_INET;
        sin.sin_port = htons(iPort);
        sin.sin_addr.S_un.S_addr = INADDR_ANY;
        
        if (SOCKET_ERROR == bind(serverListen,(SOCKADDR*)&sin,sizeof(sin)))
        {
            return FALSE;
        }
        
        if (SOCKET_ERROR == listen(serverListen,2)) 
        {
            return FALSE;
        }
        
        sListen = serverListen;
        
        return TRUE;
    }//向客户端发包
    int  mySendDataToCli(SOCKET sockClient,char *msgToClient)
    {
        int len  = 0;
        
        if (strlen(msgToClient)>0)
        {
            len = send(sockClient,msgToClient,strlen(msgToClient),0);
        }  
        
        return len;
    }//循环收发数据包
    BOOL  myLoop(int iFlag)
    {   
        BOOL bRet = myInitSocket();
        if (FALSE == bRet)
        {
            AfxMessageBox("SOCKET库初始化失败");
            return FALSE;
        }
        
        SOCKET myListenSocket;
        bRet = myBindSocket(myListenSocket,4567); 
        if (FALSE == bRet)
        {
            AfxMessageBox("监听失败");
            return FALSE;  
        }
        
        SOCKADDR_IN remoteAddr;
        int nAddrLen = sizeof(remoteAddr);
        SOCKET sClient;
        char szText[] = "Hello Client!\r\n";
        
        while (iFlag) //标记线程是否退出
        {
            sClient = accept(myListenSocket,(SOCKADDR*)&remoteAddr,&nAddrLen);
            
            if (INVALID_SOCKET == sClient)
            {
                continue;
            }
            
            int len =  mySendDataToCli(sClient,szText);
            
            char reevBuf[256];         //没有数据可接收的话,会在这里一直阻塞
            len=    recv(sClient,reevBuf,256,0);
            reevBuf[len] = '\0';
            
            if (len > 0)
            {
                CString strRecvMsg = "客户端发来的消息";
                strRecvMsg.Insert(strRecvMsg.GetLength(),reevBuf);
                AfxMessageBox(strRecvMsg );
            }
            else
            {
                AfxMessageBox("接受客户端数据包失败");
            }
        }
        
        closesocket(sClient);
        closesocket(myListenSocket);
        
        return TRUE;
    }////////////////////////////////////////////////// myMFCServerDlg.h 
    // MFC窗体头文件class CMyMFCServerDlg : public CDialog
    {
        // Implementation
    public:
        //跟线程相关的参数
        static  int bFlag; 
        HANDLE  hThread; 
        DWORD   threadID;        
        static  DWORD WINAPI  ThreadProc(void*  pObj); 
        bool    Start(CMyMFCServerDlg*  pObj); 
    };///////////////////////////////////////////////// myMFCServerDlg.cpp
    // MFC窗体源文件#include "stdafx.h"
    #include "myMFCServer.h"
    #include "myMFCServerDlg.h"//封装SOCKET操作的类
    #include "mySocketManager.h"//#include "winsock2.h"        
    #pragma   comment(lib,"ws2_32.lib") //线程是否退出的标记
    int CMyMFCServerDlg::bFlag = 1; //启动服务
    void CMyMFCServerDlg::OnButton1() 
    {
        hThread = CreateThread(NULL,0,ThreadProc,this,0,&threadID);   
    }//子线程入口函数
    DWORD WINAPI  CMyMFCServerDlg::ThreadProc(void*   pObj) 

        CMyMFCServerDlg*  pThis = (CMyMFCServerDlg*)pObj; 
        pThis->Start(pThis);  
        return   0; 
    } //子线程功能函数
    bool CMyMFCServerDlg::Start(CMyMFCServerDlg*  pObj) 
    {      
        myLoop(bFlag);    
        AfxMessageBox("客户端子线程退出循环"); 
        return TRUE; 
    } //停止服务
    void CMyMFCServerDlg::OnButton2() 
    {   
        CMyMFCServerDlg::bFlag = 0;
        
        if (hThread != NULL) 
        { 
            //等待线程正常退出
            WaitForSingleObject(hThread,2000); 
            
            if (hThread != NULL) 
            { 
                CloseHandle(hThread); 
            } 
        } 
        
        DWORD m; 
        GetExitCodeThread(hThread,&m); 
        if ( m == STILL_ACTIVE ) 
        {   //强制关闭线程
            TerminateThread(hThread,m); 
        }   
        hThread = NULL; 
    }
     
      

  2.   

    //客户端代码 TCP协议// mySocketManager.h
    // 封装SOCKET操作类的头文件 #pragma   comment(lib,"ws2_32.lib") #pragma pack(1)extern BOOL myInitSocket(); //初始化Socket相关的库
    extern BOOL myInitSocket(SOCKET &s,SOCKADDR_IN & servAddr,CString strIP,int iPort);
    extern BOOL myConnShuJuShouFa(SOCKET s,SOCKADDR_IN addr);
    extern int  mySendDataToServer(SOCKET sockClient,char *msgToClient);
    extern BOOL myLoop(int iFlag);#pragma pack()/////////////////////////////////////////////////
    // mySocketManager.cpp: 
    // 封装SOCKET操作
    /////////////////////////////////////////////////#include "mySocketManager.h"//初始化Socket相关的库
    BOOL myInitSocket() 
    {
        WSADATA  wsadata; 
        if(WSAStartup(MAKEWORD(2,2),&wsadata)) 
        {
            return FALSE;
        }
        
        return TRUE;
    }//创建SOCKET
    BOOL myInitSocket(SOCKET &s,SOCKADDR_IN & servAddr,CString strIP,int iPort)
    {
        SOCKET newSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        
        if (INVALID_SOCKET == newSocket)
        {    
            return FALSE;
        }
        
        SOCKADDR_IN sAddr;
        sAddr.sin_family = AF_INET;
        sAddr.sin_port = htons(iPort);
        sAddr.sin_addr.S_un.S_addr = inet_addr(strIP);
        
        s = newSocket;
        servAddr = sAddr;
        
        return TRUE;
    }//连接服务器
    BOOL myConnShuJuShouFa(SOCKET s,SOCKADDR_IN addr)
    {
        int connSerResult = connect(s,(SOCKADDR*)&addr,sizeof(addr));
        
        if (-1 == connSerResult)
        {
            return FALSE;
        }
        
        return TRUE;
    }//向服务器端发包
    int  mySendDataToServer(SOCKET sockClient,char *msgToClient)
    {
        int len  = 0;
        
        if (strlen(msgToClient)>0)
        {
            len = send(sockClient,msgToClient,strlen(msgToClient),0);
        }  
        
        return len;
    }//循环向服务器收发数据包
    BOOL myLoop(int iFlag)
    {
        BOOL bRet =  myInitSocket(); 
        
        if (FALSE == bRet)
        {
            AfxMessageBox("SOCKET库初始化失败");
            return FALSE;
        }
        
        SOCKET mySocket;
        SOCKADDR_IN addr;    //设置连接服务器的IP地址和端口
        bRet =  myInitSocket(mySocket,addr,"192.168.1.2",4567);
        
        if (FALSE == bRet)
        {
            AfxMessageBox("客户端Socket创建失败");
            return FALSE;
        }
        
        bRet =  myConnShuJuShouFa(mySocket,addr);
        
        if (FALSE == bRet)
        {
            AfxMessageBox("连接服务器失败");
            return FALSE;
        }
        
        char recvBuf[256];
        char sendBuf[256];
        memset(sendBuf,0,256);
        memcpy(sendBuf,"Hello,Server",strlen("Hello,Server")+1);
        
        int nRecv;
        int nSend;
        
        //iFlag用来标记是否退出死循环
        while (iFlag) 
        {
            //没有数据的话,会一直阻塞
            nRecv = recv(mySocket,recvBuf,256,0);
            recvBuf[nRecv] = '\0';
            
            if (nRecv >0)
            {
                CString strRecv = recvBuf;
                strRecv = "Server发来的包:\r\n" +strRecv;
                AfxMessageBox(strRecv);
            }
            else
            {
                AfxMessageBox("接收服务器发来的包失败");
            }
            
            nSend = mySendDataToServer(mySocket,sendBuf);
            
            if (nSend <1)
            {
                AfxMessageBox("向服务器发包失败");
            }
        }
        
        return TRUE;
    }
    //////////////////////////////////////// xinlingcaijiDlg.h 
    // MFC窗体头文件class CXinlingcaijiDlg : public CDialog
    {
        // Implementation
    public:
        //跟线程相关的参数
        static  int bFlag; 
        HANDLE  hThread; 
        DWORD   threadID;        
        static  DWORD WINAPI  ThreadProc(void*  pObj); 
        bool    Start(CXinlingcaijiDlg*  pObj);
    };///////////////////////////////////////////
    // xinlingcaijiDlg.cpp 
    // MFC窗体源文件 #include "stdafx.h"
    #include "xinlingcaiji.h"
    #include "xinlingcaijiDlg.h"//SOCKET操作类
    #include "mySocketManager.h"//线程是否退出的标记
    int CXinlingcaijiDlg::bFlag = 1; //启动线程,向服务器循环收发数据包
    void CXinlingcaijiDlg::OnButton1() 
    {
        hThread = CreateThread(NULL,0,ThreadProc,this,0,&threadID);   
    }//子线程入口函数
    DWORD WINAPI  CXinlingcaijiDlg::ThreadProc(void*   pObj) 

        CXinlingcaijiDlg*  pThis = (CXinlingcaijiDlg*)pObj; 
        pThis->Start(pThis);  
        return   0; 
    } //子线程功能函数
    bool CXinlingcaijiDlg::Start(CXinlingcaijiDlg*  pObj) 
    {      
        myLoop(bFlag);    
        AfxMessageBox("客户端子线程退出循环"); 
        return TRUE; 
    } //断开连接
    void CXinlingcaijiDlg::OnButton2() 
    {
        //修改Static变量
        CXinlingcaijiDlg::bFlag = 0;
        
        if (hThread != NULL) 
        { 
            //等待线程正常退出
            WaitForSingleObject(hThread,2000); 
            
            if (hThread != NULL) 
            { 
                CloseHandle(hThread); 
            } 
        } 
        
        DWORD m; 
        GetExitCodeThread(hThread,&m); 
        if ( m == STILL_ACTIVE ) 
        {   //强制关闭线程
            TerminateThread(hThread,m); 
        }   
        hThread = NULL; 
    }