入题,谢谢!

解决方案 »

  1.   

    TCP穿透中Client代理等待TCP连接的代码DWORD WINAPI ThreadProcRequest(LPVOID pParam)
    {
    #define BUF_LEN 100
    bool bOptNODELAY = true;
    sockaddr_in addRemote = *((sockaddr_in*)pParam); //ÇëÇóÁ¬½ÓµÄ¿Í»§µØÖ·
    sockaddr_in addLocal;
    SOCKET skListen = INVALID_SOCKET;
    unsigned short nPortLocal = 0;
    unsigned short nPortGlobal = 0;
    char szBuf[BUF_LEN + 1];
    int nMaxListenQueen = 5; printf("%s\tThread Proc Request: Recved connect request IP %s Port %d\n",
    GetSystemTimeAsString(), inet_ntoa(addRemote.sin_addr), ntohs(addRemote.sin_port));
    //´´½¨Ò»¸ö¾ßÓй̶¨È«¾Ö¶Ë¿ÚµÄsocket
    CreateSocketWithGlobalPort(&skListen,
    &nPortLocal, 
    &nPortGlobal, 
    g_nNATType);
    sprintf(szBuf, "%d", nPortGlobal);
    ::CreateInetAddr(&addLocal, INADDR_ANY, nPortLocal);
    //֪ͨ¶Ô·½×Ô¼ºµÄÈ«¾Ö¶Ë¿Ú
    printf("%s\tThread Proc Request: Notify My global port may be %d\n", 
    GetSystemTimeAsString(), nPortGlobal);
    ::send(g_sktComProxy, szBuf, strlen(szBuf), 0);

    //È»ºó¿ªÊ¼¼àÌýÒÔ¼°Ïò¿Í»§·¢ÆðÁ¬½Ó
    ::listen(skListen, nMaxListenQueen); //½¨Á¢Á¬½ÓµÄ¹ý³Ì
    int nConnectCount = 0;
    fd_set fdSocket;
    timeval tv = {0, 1};
    FD_ZERO(&fdSocket);
    FD_SET(skListen, &fdSocket); while (true)
    {
    nConnectCount++;
    fd_set fdRead = fdSocket;
    int nRet = select(0, &fdRead, NULL, NULL, &tv);
    if (SOCKET_ERROR == nRet)
    {
    printf("%s\tThread Proc Request: Can not accept socket, error code: %d\n", GetSystemTimeAsString(), WSAGetLastError());
    }
    else if (0 == nRet)
    {
    //nothing
    printf("%s\tThread Proc Request: %d st: did not got the client, send hole punching packet...\n", GetSystemTimeAsString(), nConnectCount);
    //²»ÄÜÊÕµ½¿Í»§Á¬½Ó£¬¼ÌÐø·¢ËÍsyn
    SOCKET skForHole = INVALID_SOCKET;
    ::SendAHolePunchingPacket(&skForHole, addRemote, addLocal);
    Sleep(3000);
    }
    else
    {
    sockaddr_in add;
    int nLen = sizeof add;
    SOCKET skClient = accept(skListen, (sockaddr*)&add, &nLen);
    if (INVALID_SOCKET == skClient)
    {
    printf("%s\tThread Proc Request: Can not accept socket, error code: %d\n", GetSystemTimeAsString(), WSAGetLastError());
    ExitThread(0);
    }
    else
    {
    int nLenMsg = 0;
    printf("%s\tThread Proc Request: Got Client succed!\n", GetSystemTimeAsString());
    sprintf(szBuf, "Hello, tcp connection established!\n");
    ::send(skClient, szBuf, strlen(szBuf), 0);
    while ((nLenMsg = ::recv(skClient, szBuf, BUF_LEN, 0)) > 0)
    {
    szBuf[nLenMsg] = 0;
    printf("%s\tMsg: %s\n", GetSystemTimeAsString(), szBuf);
    ::send(skClient, szBuf, nLenMsg, 0);
    }
    printf("%s\tThread Proc Request: Client closed the socket!\n", GetSystemTimeAsString());
    closesocket(skClient);
    }
    break;
    }
    }

    closesocket(skListen);
    ExitThread(1);
    return 1;
    #undef BUF_LEN
    }
      

  2.   

    发送打洞包的代码,该段代码将在NAT上临时建立起端口映射:bool SendAHolePunchingPacket(SOCKET *skt, sockaddr_in addRemote, sockaddr_in addLocal)
    {
    VERIFY(NULL != skt);
    bool bOpt = true;
    int nMod = 1;
    *skt = INVALID_SOCKET;
    VERIFY_SOCKET(INVALID_SOCKET != (*skt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)));
    setsockopt(*skt, SOL_SOCKET, SO_REUSEADDR, (char*)&bOpt, sizeof bOpt);
    VERIFY_SOCKET(SOCKET_ERROR != (bind(*skt, (sockaddr*)&addLocal, sizeof addLocal)));
    //ioctlsocket(*skt,  FIONBIO, (unsigned long*)&nMod);
    printf("%s\tHole Punching: holing %s %d to remote %s %d ...\n", GetSystemTimeAsString(), inet_ntoa(addLocal.sin_addr), 
    ntohs(addLocal.sin_port), inet_ntoa(addRemote.sin_addr), ntohs(addRemote.sin_port));
    int nRet = connect(*skt, (sockaddr*)&addRemote, sizeof addRemote);
    if (SOCKET_ERROR == nRet)
    {
    printf("%s\tHole Punching: error code: %d\n", GetSystemTimeAsString(), WSAGetLastError());
    } ::ForceCloseSocket(skt);
    return true;
    }