WEB开发网
开发学院软件开发VC TCP实现P2P通信、TCP穿越NAT的方法、TCP打洞 阅读

TCP实现P2P通信、TCP穿越NAT的方法、TCP打洞

 2010-07-25 20:46:50 来源:WEB开发网   
核心提示:客户端B收到服务器S的打洞通知后,先连接S的【协助打洞】端口号(本地端口号可以用GetSocketName()函数取得,TCP实现P2P通信、TCP穿越NAT的方法、TCP打洞(5),假设为X),启动线程尝试连接客户端A的公网IP和端口号,等待客户端A直接连接该端口号, 执行者:客户端A// 服务器要求主动端(客户端A

客户端B收到服务器S的打洞通知后,先连接S的【协助打洞】端口号(本地端口号可以用GetSocketName()函数取得,假设为X),启动线程尝试连接客户端A的公网IP和端口号,根据路由器不同,连接情况各异,如果运气好直接连接就成功了,即使连接失败,但打洞便完成了。同时还要启动线程在相同的端口(即与S的【协助打洞】端口号建立连接的本地端口号X)上侦听到来的连接,等待客户端A直接连接该端口号。//
// 执行者:客户端A
// 服务器要求主动端(客户端A)直接连接被动端(客户端B)的外部IP和端口号
//
BOOL Handle_SrvReqDirectConnect ( t_SrvReqDirectConnectPkt *pSrvReqDirectConnectPkt )
{
   ASSERT ( pSrvReqDirectConnectPkt );
   printf ( "You can connect direct to ( IP:%s PORT:%d ID:%u )
", pSrvReqDirectConnectPkt->szInvitedIP,
     pSrvReqDirectConnectPkt->nInvitedPort, pSrvReqDirectConnectPkt->dwInvitedID );
   // 直接与客户端B建立TCP连接,如果连接成功说明TCP打洞已经成功了。
   CSocket Sock;
   try
   {
     if ( !Sock.Socket () )
     {
       printf ( "Create socket failed : %s
", hwFormatMessage(GetLastError()) );
       return FALSE;
     }
     UINT nOptValue = 1;
     if ( !Sock.SetSockOpt ( SO_REUSEADDR, &nOptValue , sizeof(UINT) ) )
     {
       printf ( "SetSockOpt socket failed : %s
", hwFormatMessage(GetLastError()) );
       return FALSE;
     }
     if ( !Sock.Bind ( g_nHolePort ) )
     {
       printf ( "Bind socket failed : %s
", hwFormatMessage(GetLastError()) );
       return FALSE;
     }
     for ( int ii=0; ii<100; ii++ )
     {
       if ( WaitForSingleObject ( g_hEvt_ConnectOK, 0 ) == WAIT_OBJECT_0 )
         break;
       DWORD dwArg = 1;
       if ( !Sock.IOCtl ( FIONBIO, &dwArg ) )
       {
         printf ( "IOCtl failed : %s
", hwFormatMessage(GetLastError()) );
       }
       if ( !Sock.Connect ( pSrvReqDirectConnectPkt->szInvitedIP, pSrvReqDirectConnectPkt->nInvitedPort ) )
       {
         printf ( "Connect to [%s:%d] failed : %s
",
           pSrvReqDirectConnectPkt->szInvitedIP,
           pSrvReqDirectConnectPkt->nInvitedPort,
           hwFormatMessage(GetLastError()) );
           Sleep (100);
       }
       else break;
     }
     if ( WaitForSingleObject ( g_hEvt_ConnectOK, 0 ) != WAIT_OBJECT_0 )
     {
       if ( HANDLE_IS_VALID ( g_hEvt_ConnectOK ) ) SetEvent ( g_hEvt_ConnectOK );
       printf ( "Connect to [%s:%d] successfully !!!
",
       pSrvReqDirectConnectPkt->szInvitedIP, pSrvReqDirectConnectPkt->nInvitedPort );
      
       // 接收测试数据
       printf ( "Receiving data ...
" );
       char szRecvBuffer[NET_BUFFER_SIZE] = {0};
       int nRecvBytes = 0;
       for ( int i=0; i<1000; i++ )
       {
         nRecvBytes = Sock.Receive ( szRecvBuffer, sizeof(szRecvBuffer) );
         if ( nRecvBytes > 0 )
         {
           printf ( "-->>> Received Data : %s
", szRecvBuffer );
           memset ( szRecvBuffer, 0, sizeof(szRecvBuffer) );
           SLEEP_BREAK ( 1 );
         }
         else
         {
           SLEEP_BREAK ( 300 );
         }
       }
     }
   }
   catch ( CException e )
   {
     char szError[255] = {0};
     e.GetErrorMessage( szError, sizeof(szError) );
     printf ( "Exception occur, %s
", szError );
     return FALSE;
   }
   return TRUE;
}

上一页  1 2 3 4 5 6  下一页

Tags:TCP 实现 PP

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接