我要在客户端每隔30秒向服务器端发送数据,采用TCP/IP协议,协议格式已经定好了。我自己封装了一个SOCKET类CMySocket,在这个类里将SOCKET的一些API函数重新封装了一下。
class CMySocket  
{
  SOCKET m_socket;
  
  void InitSocket();  //加载库并创建SOCKET实例m_socket
  BOOL ConnectServ();  //连接服务器
  void SendData(char *,int nLength);  //发送数据
  void RecvData(char *,int nLength);  //接收数据
}
然后我在主线程对话框类头文件里定义了一个CMySocket对象m_sockClient。为了防止主线程阻塞,我想采用多线程的办法。在对话框的OnInitDialog()函数里用AfxBeginThread创建一个工作线程。
BOOL CTestClientDlg::OnInitDialog()
{
  ...
  m_sockClient.InitSocket();
  AfxBeginThread(ConnectThread,);  /// ??
}我有几个疑问:1. 在线程之间传递MFC对象和SOCKET对象不安全,只能选择传递句柄。那我怎么将m_sockClient对象传递给线程函数?要是传递句柄的话那我岂不是没办法调用CMySocket对象的成员函数了。2. 我是在在ConnectServ()函数里调用connect函数连接的服务器端,因为我要周期性的发送数据给服务器,为保证始终都处于连接状态,那我在一个while死循环调用connect函数是否可行?3. 当我在SendData(char *,int nLength)函数里调用send函数向服务器发送数据时,我如何知道当前与服务器是处在连接状态,还是断掉?怎么得到这一信息?4. 我要周期性的发送数据,那是不是只要周期性的调用send函数就可以了?5. 当我按照指定的协议格式将数据发送过去后,是不是一定能保证数据准确被接收?万一不能被准确接收,我该怎么操作才能保证传输过去的数据不会出错?本人刚刚开始接触TCP网络编程,所以可能问的问题有点多,也很菜:),希望大家不吝赐教,在此致谢。

解决方案 »

  1.   

    1、如果说传递对象不安全,那么传递句柄也一样不安全,最好不要多线程共用一个Socket。
    2、是否用死循环完全是个人爱好,不过最好能够再加一些错误判断和处理。
    3、如果Send返回错误,根据错误码可以判断。
    4、在不出错的情况下是这样。
    5、Send返回成功就表示数据已经被准确接收,如果Send返回失败,则要根据错误码来判断问题,并决定是否重新连接。
      

  2.   

    1.AfxBeginThread(ConnectThread,m_sockClient);在工作线程里:CMySocket mySocket = (CMySocket)pParam;
    2-4.可以设置一个时钟,在时钟函数里ConnectServ(),连接成功后再SendData。
    5.Send只能表示数据被成功发送,并不能保证在接受端数据被准确接受。一定能保证数据准确被接收
    ----------------------------
    这个有点复杂了,其实在你的程序中也可以做,有三次握手规则。
      

  3.   

    1.   在线程之间传递MFC对象和SOCKET对象不安全,只能选择传递句柄。那我怎么将m_sockClient对象传递给线程函数?要是传递句柄的话那我岂不是没办法调用CMySocket对象的成员函数了。 
    你可以将 ConnectThread 当作 CTestClientDlg 类的成员函数,启动线程的时候直接将this传给它,但由于ConnectThread 是一个静态函数,你需要一个辅助函数才行,可以用this来调用:
    unsigned int CTestClientDlg::ConnectThread(void *param)
    {
        CTestClientDlg *pThis = (CTestClientDlg *)param;
        return pThis->ConnectThreadFunction(); // 这样你就能直接访问类中的成员了
    }2.   我是在在ConnectServ()函数里调用connect函数连接的服务器端,因为我要周期性的发送数据给服务器,为保证始终都处于连接状态,那我在一个while死循环调用connect函数是否可行? 
    你为什么要反复的调用connect函数?如果是短连接的话,用udp不是更合适吗?
    3.   当我在SendData(char   *,int   nLength)函数里调用send函数向服务器发送数据时,我如何知道当前与服务器是处在连接状态,还是断掉?怎么得到这一信息? 
    根据send的返回值,socket_error表示出错。4.   我要周期性的发送数据,那是不是只要周期性的调用send函数就可以了? 
    可以用一个timer或是启动一个线程5.   当我按照指定的协议格式将数据发送过去后,是不是一定能保证数据准确被接收?万一不能被准确接收,我该怎么操作才能保证传输过去的数据不会出错? 
    tcp/ip 属于稳定传输,只要能发送成功,就能保证正确接收。为了更加保险起见,服务端收到数据后应该给客户端回一条确认消息
      

  4.   

    1.   在线程之间传递MFC对象和SOCKET对象不安全,只能选择传递句柄。那我怎么将m_sockClient对象传递给线程函数?要是传递句柄的话那我岂不是没办法调用CMySocket对象的成员函数了。 
          你可以将m_sockClient的指针传过去。如果你自己封装的Socket与线程无关传递对象也可以。2.   我是在在ConnectServ()函数里调用connect函数连接的服务器端,因为我要周期性的发送数据给服务器,为保证始终都处于连接状态,那我在一个while死循环调用connect函数是否可行? 
       如果始终都处于连接状态你就没有必要一直connect服务器了。你只需要周期性的判断一下服务器是否关闭就行了。如果你的connect每次都返回一个新的socket是不是比较浪费?3.   当我在SendData(char   *,int   nLength)函数里调用send函数向服务器发送数据时,我如何知道当前与服务器是处在连接状态,还是断掉?怎么得到这一信息? 
       send函数的返回值,看看getlasterror就知道了。4.   我要周期性的发送数据,那是不是只要周期性的调用send函数就可以了? 
       一次connect,周期性的使用connect返回的socket去send数据就可以了。如果你是带界面的程序用timer可以,如果是控制台程序你就得自己dispatch消息。5.   当我按照指定的协议格式将数据发送过去后,是不是一定能保证数据准确被接收?万一不能被准确接收,我该怎么操作才能保证传输过去的数据不会出错? 
       你可以使用CRC校验一下你发送与接收的数据是否正确。如果接收正确可以返回一个类似ACK的信息。如果传过去的数据不正确你可以根据返回的信息决定是否重新发送。6、异步socket处理起来相对麻烦一些。如果你需要定期去connect连接远程服务器,调用connect函数时如果服务器关闭或你连接的ip不正确阻塞模式的socket会有一段等时间,最长应该是75秒。这时候你可以选用异步socket来connect使用select来确定是否连接成功。当连接成功时你可以再设为阻塞方式来处理。
      

  5.   

    一般是两个线程嘛,一个线程接数据,一个线程发数据,因为socket是双工的嘛!