#define SRV_TCP_MAIN_PORT 4000
// 服务器主连接的端口号#
define SRV_TCP_HOLE_PORT 8000
// 服务器响应客户端打洞申请的端口号
这两个端口是固定的,服务器 S 启动时就开始侦听这两个端口了。
//// 将新客户端登录信息发送给所有已登录的客户端,但不发送给自己//
BOOL SendNewUserLoginNotifyToAll ( LPCTSTR lpszClientIP, UINT nClientPort, DWORD
dwID ){ ASSERT ( lpszClientIP && nClientPort > 0 ); g_CSFor_PtrAry_SockClient.Lock();
for ( int i=0; i<g_PtrAry_SockClient.GetSize(); i++ ) { CSockClient *pSockClient
= (CSockClient*)g_PtrAry_SockClient.GetAt(i); if ( pSockClient && pSockClient-
>m_bMainConn && pSockClient->m_dwID > 0 && pSockClient->m_dwID != dwID ) {
if ( !pSockClient->SendNewUserLoginNotify ( lpszClientIP, nClientPort, dwID ) )
{ g_CSFor_PtrAry_SockClient.Unlock(); return
FALSE; } } } g_CSFor_PtrAry_SockClient.Unlock (); return
TRUE;}
当有新的客户端连接到服务器时,服务器负责将该客户端的信息(IP 地址、端口号)发送
给其他客户端。
//// 执 行 者 : 客 户 端 A// 有 新 客 户 端 B 登 录 了 , 我 ( 客 户 端 A ) 连 接 服 务 器 端 口
SRV_TCP_HOLE_PORT , 申 请 与 客 户 端 B 建 立 直 接 的 TCP 连 接 //BOOL
Handle_NewUserLogin ( CSocket &MainSock, t_NewUserLoginPkt *pNewUserLoginPkt ){
printf ( "New user ( %s:%u:%u ) login server\n", pNewUserLoginPkt->szClientIP,
pNewUserLoginPkt->nClientPort, pNewUserLoginPkt->dwID ); BOOL bRet = FALSE;
DWORD dwThreadID = 0; t_ReqConnClientPkt ReqConnClientPkt; CSocket Sock;
CString csSocketAddress; char szRecvBuffer[NET_BUFFER_SIZE] = {0}; int
nRecvBytes = 0; // 创 建 打 洞 Socket , 连 接 服 务 器 协 助 打 洞 的 端 口 号
SRV_TCP_HOLE_PORT try { if ( !Sock.Socket () ) { printf
( "Create socket failed : %s\n", hwFormatMessage(GetLastError()) ); goto finished;
} UINT nOptValue = 1; if ( !Sock.SetSockOpt ( SO_REUSEADDR,
&nOptValue , sizeof(UINT) ) ) { printf ( "SetSockOpt socket failed : %s\n",
hwFormatMessage(GetLastError()) ); goto finished; } if ( !Sock.Bind ( 0
) ) { printf ( "Bind socket failed : %s\n", hwFormatMessage(GetLastError()) );
goto finished; } if ( !Sock.Connect ( g_pServerAddess,
SRV_TCP_HOLE_PORT ) ) { printf ( "Connect to [%s:%d] failed : %s\n",
g_pServerAddess, SRV_TCP_HOLE_PORT,
hwFormatMessage(GetLastError()) ); goto finished; } } catch
( CException e ) { char szError[255] = {0}; e.GetErrorMessage( szError,
sizeof(szError) ); printf ( "Exception occur, %s\n", szError ); goto finished; }
g_pSock_MakeHole = &Sock; ASSERT ( g_nHolePort == 0 ); VERIFY
( Sock.GetSockName ( csSocketAddress, g_nHolePort ) ); // 创 建 一 个 线 程 来 侦 听 端 口
g_nHolePort 的连接请求 dwThreadID = 0; g_hThread_Listen = ::CreateThread ( NULL,
0, ::ThreadProc_Listen, LPVOID(NULL), 0, &dwThreadID ); if (!
HANDLE_IS_VALID(g_hThread_Listen) ) return FALSE; Sleep ( 3000 );// 我(客户端 A)向
服务器协助打洞的端口号 SRV_TCP_HOLE_PORT 发送申请,希望与新登录的客户端 B 建
- 1
- 2
- 3
前往页