没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
这里假设客户端 A 先启动,当客户端 B 启动后客户端 A 将收到服务器 S 的新客户端登录的
通知,并得到客户端 B 的公网 IP 和端口,客户端 A 启动线程连接 S 的【协助打洞】端口
(本地端口号可以用 GetSocketName()函数取得,假设为 M),请求 S 协助 TCP 打洞,然后启
动线程侦听该本地端口(前面假设的 M)上的连接请求,然后等待服务器的回应。
//
// 客户端 A 请求我(服务器)协助连接客户端 B,这个包应该在打洞 Socket 中收到
//
BOOL CSockClient::Handle_ReqConnClientPkt(t_ReqConnClientPkt *pReqConnClientPkt)
{
ASSERT ( !m_bMainConn );
CSockClient *pSockClient_B = FindSocketClient ( pReqConnClientPkt->dwInvitedID );
if ( !pSockClient_B ) return FALSE;
printf ( "%s:%u:%u invite %s:%u:%u connection
", m_csPeerAddress, m_nPeerPort, m_dwID,
pSockClient_B->m_csPeerAddress, pSockClient_B->m_nPeerPort, pSockClient_B-
>m_dwID );
// 客户端 A 想要和客户端 B 建立直接的 TCP 连接,服务器负责将 A 的外部 IP 和端口
号告诉给 B
t_SrvReqMakeHolePkt SrvReqMakeHolePkt;
SrvReqMakeHolePkt.dwInviterID = pReqConnClientPkt->dwInviterID;
SrvReqMakeHolePkt.dwInviterHoleID = m_dwID;
SrvReqMakeHolePkt.dwInvitedID = pReqConnClientPkt->dwInvitedID;
STRNCPY_CS ( SrvReqMakeHolePkt.szClientHoleIP, m_csPeerAddress );
SrvReqMakeHolePkt.nClientHolePort = m_nPeerPort;
if ( pSockClient_B->SendChunk ( &SrvReqMakeHolePkt, sizeof(t_SrvReqMakeHolePkt), 0
) != sizeof(t_SrvReqMakeHolePkt) )
return FALSE;
// 等待客户端 B 打洞完成,完成以后通知客户端 A 直接连接客户端外部 IP 和端口号
if ( !HANDLE_IS_VALID(m_hEvtWaitClientBHole) )
return FALSE;
if ( WaitForSingleObject ( m_hEvtWaitClientBHole, 6000*1000 ) == WAIT_OBJECT_0 )
{
if ( SendChunk ( &m_SrvReqDirectConnectPkt, sizeof(t_SrvReqDirectConnectPkt), 0 )
== sizeof(t_SrvReqDirectConnectPkt) )
return TRUE;
}
return FALSE;
}
服务器 S 收到客户端 A 的协助打洞请求后通知客户端 B,要求客户端 B 向客户端 A 打洞,
即让客户端 B 尝试与客户端 A 的公网 IP 和端口进行 connect。
//
// 执行者:客户端 B
// 处理服务器要我(客户端 B)向另外一个客户端(A)打洞,打洞操作在线程中进行。
// 先连接服务器协助打洞的端口号 SRV_TCP_HOLE_PORT ,通过服务器告诉客户端 A 我
资源评论
老帽爬新坡
- 粉丝: 81
- 资源: 2万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功