gpt4 book ai didi

networking - 如何控制peer上的socket[TCP Hole Punching]

转载 作者:可可西里 更新时间:2023-11-01 02:43:52 24 4
gpt4 key购买 nike

我有一个使用 TCP 连接进行通信的服务器-客户端程序。多个客户端可以同时连接到服务器。我想在这个系统上实现tcp hole punching。

在客户端,它调用公共(public)服务器来查找我的服务器的公共(public) ip、端口。然后连接到它。

但是在服务器端它必须打开一个端口来连接到公共(public)服务器,并且它还必须在同一个端口上接受客户端连接请求。

我要做的是打开一个套接字并绑定(bind)到端口X,然后连接到公共(public)服务器,然后将这个套接字更改为监听状态以接受传入连接一段时间,然后开始连接到公共(public)服务器一次又一次。

这是正确的方法吗?

编辑:我有另一个想法。就是开一个新的端口,连接公用服务器。主服务器端口照常监听传入连接。当客户端要连接时,公共(public)服务器将通过新端口告诉我的服务器。它将阻止主端口监听传入连接,而是连接到客户端进行打洞。然后它连接到公共(public)服务器,它将服务器公共(public) ip 地址转发给客户端,并像往常一样返回监听传入连接。然后客户端将使用此地址连接到已打开 TCP 漏洞的服务器。

最佳答案

最好有两个套接字,并保持服务器和客户端之间的独立连接。

  1. m_nServerTCPSocket- 用于与服务器连接和监听套接字

  2. m_nPeerPrivateTCPSocket- 连接对端(公共(public)地址)

  3. m_nPeerPublicTCPSocket- 与对等点连接(如果其他对等点在同一网络中,则为私有(private)地址)

  4. m_nListeningTCPSocket - 用于监听对端的套接字,您需要接受来自对端的连接。
  5. m_nConnectedPeerTCPSocket-> 一旦与其他对等方连接,您就会获得此套接字。

    while(end_client)    
    {

    FD_ZERO(&fdRead);
    FD_ZERO(&fdWrite);
    FD_ZERO(&fdExcept);

    if (pControlMgr->GetConnectionMgr()->GetListeningTCPSocket()>0)

    {

    FD_SET (pControlMgr->GetConnectionMgr()->GetListeningTCPSocket(),&fdRead);
    FD_SET (pControlMgr->GetConnectionMgr()->GetListeningTCPSocket(),&fdExcept);
    }

    if (pControlMgr->GetConnectionMgr()->GetServerTCPSocket()>0)
    {

    FD_SET (pControlMgr->GetConnectionMgr()->GetServerTCPSocket(),&fdRead);
    FD_SET (pControlMgr->GetConnectionMgr()->GetServerTCPSocket(),&fdExcept);
    }
    if (pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket()>0)
    {
    FD_SET (pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(),&fdRead);
    FD_SET (pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(),&fdExcept);
    }

    timeval tv;
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    nSelectRetVal = select(NULL,&fdRead,NULL,&fdExcept,&tv);


    if (nSelectRetVal>0)
    {
    int nRecvRetVal = 0;
    /* TCP Server Socket handling */
    if ( FD_ISSET(pControlMgr->GetConnectionMgr()->GetServerTCPSocket(), &fdRead ))
    {
    try
    {
    pRecvBuffer = new char[TCP_RECV_SIZE];
    nRecvRetVal = recv(pControlMgr->GetConnectionMgr()->GetServerTCPSocket(),
    pRecvBuffer,TCP_RECV_SIZE,
    0);
    int n = WSAGetLastError();
    if (nRecvRetVal>0)
    {
    int nPeerNameRetVal = getpeername(pControlMgr->GetConnectionMgr()->GetServerTCPSocket(),(sockaddr*)&addrRemotePeer,&nSockAddrLen);
    if ( pControlMgr->HandlePacket(pRecvBuffer,addrRemotePeer)== -1 )
    {
    if ( NULL != pRecvBuffer)
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    return 0 ;
    }
    }
    }
    }
    catch (...)
    {
    if ( NULL != pRecvBuffer )
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    }
    }

    if ( NULL != pRecvBuffer)
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    }
    } /* TCP Server Socket handling */

    int n;
    /* TCP Exception Server Socket handling */
    if ( FD_ISSET(pControlMgr->GetConnectionMgr()->GetServerTCPSocket(), &fdExcept ))
    {
    /*FD_CLR(pControlMgr->GetConnectionMgr().GetServerTCPSocket (),&fdRead);
    FD_CLR(pControlMgr->GetConnectionMgr().GetServerTCPSocket (),&fdExcept);*/
    n = WSAGetLastError();
    //return 0;
    }
    if (FD_ISSET(pControlMgr->GetConnectionMgr()->GetListeningTCPSocket(),&fdRead))
    {
    sockaddr_in addrConnectedPeer;
    int nAddrLen =sizeof(addrConnectedPeer) ;
    int nConnectedSock = accept( pControlMgr->GetConnectionMgr()->GetListeningTCPSocket(),
    (sockaddr*)&addrConnectedPeer,
    &nAddrLen);
    int n1 = WSAGetLastError();
    if (nConnectedSock>0)
    {
    pControlMgr->GetConnectionMgr()->SetConnectedTCPSocket(nConnectedSock);
    int n = pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket();
    continue;
    }
    }
    /* TCP Exception Listening Socket handling */
    if ( FD_ISSET(pControlMgr->GetConnectionMgr()->GetListeningTCPSocket(), &fdExcept ))
    {
    FD_CLR(pControlMgr->GetConnectionMgr()->GetListeningTCPSocket (),&fdRead);
    FD_CLR(pControlMgr->GetConnectionMgr()->GetListeningTCPSocket (),&fdExcept);
    //return 0;
    } /* TCP Exception Listening Socket handling */

    /* Connected Peer TCP Read Socket handling */
    if ( FD_ISSET(pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(), &fdRead ))
    {
    try
    {
    pRecvBuffer = new char[TCP_RECV_SIZE];
    nRecvRetVal = recv (pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(),
    pRecvBuffer,TCP_RECV_SIZE,
    0);
    if (nRecvRetVal>0)
    {
    int nPeerNameRetVal = getpeername(pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(),(sockaddr*)&addrRemotePeer,&nSockAddrLen);
    if ( pControlMgr->HandlePacket(pRecvBuffer,addrRemotePeer)== -1 )
    {
    if ( NULL != pRecvBuffer)
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    return 0 ;
    }
    }
    }
    }
    catch (...)
    {
    if ( NULL != pRecvBuffer )
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    }
    }
    //FD_CLR(pControlMgr->GetConnectionMgr().GetConnectedTCPSocket(),&fdRead);
    if ( NULL != pRecvBuffer)
    {
    delete [] pRecvBuffer;
    pRecvBuffer = NULL;
    }
    } /* Peer TCP Read Socket handling */
    /* TCP Exception Connected Socket handling */
    if ( FD_ISSET(pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket(), &fdExcept ))
    {
    /*FD_CLR(pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket (),&fdRead);
    FD_CLR(pControlMgr->GetConnectionMgr()->GetConnectedTCPSocket (),&fdExcept);
    return 0;*/
    n = WSAGetLastError();
    }

创建套接字的逻辑

      int CConnectionMgr::CreateSocket(const int nSockType)
{
//TODO: Add code here
if (InitWinSock() == -1)
{
return -1;
}
SetLocalIPAddress();

m_nListeningTCPSocket = socket(AF_INET, SOCK_STREAM ,nSockType );
if ( GetListeningTCPSocket() <0 )
return -1;
if (BindSocket(GetListeningTCPSocket())<0)
return -1;
int nListenRet = listen(GetListeningTCPSocket(),SOMAXCONN);

if (nListenRet!=0)
{
return -1;
}
m_nPeerPrivateTCPSocket = socket(AF_INET, SOCK_STREAM ,nSockType );
if (GetPeerPrivateTCPSocket()<0)
return -1;
if (BindSocket(GetPeerPrivateTCPSocket())<0)
return -1;

m_nPeerPublicTCPSocket = socket(AF_INET, SOCK_STREAM ,nSockType );
if ( GetPeerPublicTCPSocket()<0)
return -1;
if (BindSocket(GetPeerPublicTCPSocket())<0)
return -1;

m_nServerTCPSocket = socket(AF_INET, SOCK_STREAM ,nSockType );
if (GetServerTCPSocket()<0)
return -1;
if (BindSocket(GetServerTCPSocket())<0)
return -1;
return 1;
}

关于networking - 如何控制peer上的socket[TCP Hole Punching],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13118144/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com