⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cpp

📁 stun的一个客户端例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	act_on_error(nRetVal = connect(sComm, (struct sockaddr *)&AddrComm, sizeof(AddrComm)), "Connecting to communication server", goto LAB_ERR_CONNECT);
	//Write the Message sent to Communication server
	MsgCon.nType = htonl(MSG_CONNECT);
	strcpy(MsgCon.Data.Connection.chDstID, pchPeerID);
	strcpy(MsgCon.Data.Connection.chSrcID, g_chClientID);
	//send the message
	log_on_write_error(sComm,  (char*)&MsgCon, sizeof(MsgCon), "Sending communication message", LAB_ERR_SEND);
	//receive the result
#ifdef TEST_TIME
#ifdef _WIN32
	nStart = GetTickCount();
#endif
#endif
    readtimeout(sComm, Socks, nTimeoutSec, LAB_ERR_COMM_TIMEOUT);	//COMM_TIMEOUT
#ifdef TEST_TIME
#ifdef _WIN32
	nEnd = GetTickCount();
	printf("Receiving communication result [%d] ms.\n", nEnd - nStart);
#endif
#endif
	log_on_read_error(sComm, (char*)&nCommRet, sizeof(nCommRet), "Receiving communication result", LAB_ERR_RECEIVE);

	if (nCommRet == -1)
	{
		close2(*psConnect);
		close2(sComm);
		return ERR_MATCH;		
	}
	else if (nCommRet != 0)
	{
		close2(*psConnect);
		close2(sComm);
		*pnErrCode = nCommRet;
		return ERR_SAME_NAT;		
	}
#ifdef TEST_TIME
#ifdef _WIN32
	nStart = GetTickCount();
#endif
#endif
    readtimeout(sServerLog, Socks, nTimeoutSec, LAB_ERR_TIMEOUT);	
#ifdef TEST_TIME
#ifdef _WIN32
	nEnd = GetTickCount();
	printf("Receiving peer data [%d] ms.\n", nEnd - nStart);
#endif
#endif
	log_on_read_error(sServerLog, (CHAR*)&Peer, sizeof(Peer), "Receiving peer data", LAB_ERR_RECEIVE);
	close2(sCtrl);
	//Assign the socket address/port of of the server (control channel port) which is returned by channel
	XInitSockAddr(&AddrCtrl, AF_INET, NULL, 0, Peer.nIP, Peer.wPort);
	//Create control channel socket
	sCtrl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	act_on_error(sCtrl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), "Creating control socket", goto LAB_ERR_CREATE_SOCKET);
	act_on_error(connect(sCtrl, (struct sockaddr *)&AddrCtrl, sizeof(AddrCtrl)), "Connecting to control server",  goto LAB_ERR_CONNECT);
	//Sync with peer
#ifdef _WIN32
	nDelay = GetTickCount();
#else
	ftime(&tStart);
#endif
	log_on_Xwrite_error(sCtrl, &nOne, sizeof(nOne), "Sending echo", LAB_ERR_SYN_SEND);
#ifdef TEST_TIME
#ifdef _WIN32
	nStart = GetTickCount();
#endif
#endif
    readtimeout(sCtrl, Socks, nTimeoutSec, LAB_ERR_ECHO_TIMEOUT);		//here we let programmer to set this value
#ifdef TEST_TIME
#ifdef _WIN32
	nEnd = GetTickCount();
	printf("Reading echo [%d] ms.\n", nEnd - nStart);
#endif
#endif
    log_on_Xread_error(sCtrl, &nOne, sizeof(nOne), "Reading echo", LAB_ERR_SYN_RECEIVE);
#ifdef _WIN32
	nDelay = GetTickCount() - nDelay;
#else
	ftime(&tCurrent);
	nDelay = (int) (1000.0 * (tCurrent.time - tStart.time)
        + (tCurrent.millitm - tStart.millitm));
#endif
	log_on_Xwrite_error(sCtrl, &nOne, sizeof(nOne), "Sending echo", LAB_ERR_SYN_SEND);
#ifdef _WIN32
	Sleep(nDelay / 2);
#else
	XSleep(0, nDelay / 2);
#endif
#ifdef TEST_TIME
#ifdef _WIN32
	nStart = GetTickCount();
#endif
#endif
	nRetVal = XAsymClient(sServerLog, sCtrl, psConnect, pAddrPeer, ASYM_TIMEOUT, &nAsymErrCode);
#ifdef TEST_TIME
#ifdef _WIN32
	nEnd = GetTickCount();
	printf("AsymClient [%d] ms.\n", nEnd - nStart);
#endif
#endif

	if (nRetVal != ERR_NONE)
	{
		*pnErrCode = nRetVal;
		close2(*psConnect);
		close2(sComm);
		close2(sCtrl);
		return ERR_ASYMCLIENT;
	}
	else
	{
		close2(sComm);
		close2(sCtrl);
		return ERR_NONE;
	}

LAB_ERR_CREATE_SOCKET:
	close2(sComm);
	close2(sCtrl);
	*pnErrCode = XGetErrno();
	return ERR_CREATE_SOCKET;

LAB_ERR_CONNECT:
	close2(sComm);
	close2(sCtrl);
	*pnErrCode = XGetErrno();
	return ERR_CONNECT;

LAB_ERR_SEND:
	close2(sComm);
	*pnErrCode = XGetErrno();
	return ERR_SEND;

LAB_ERR_COMM_TIMEOUT:
	close2(sComm);
	*pnErrCode = XGetErrno();
	return ERR_COMM_TIMEOUT;

LAB_ERR_RECEIVE:
	close2(sComm);
	*pnErrCode = XGetErrno();
	return ERR_RECEIVE;

LAB_ERR_TIMEOUT:
	close2(sComm);
	*pnErrCode = XGetErrno();
	return ERR_TIMEOUT;

LAB_ERR_ECHO_TIMEOUT:
	close2(sComm);
	close2(sCtrl);
	*pnErrCode = XGetErrno();
	return ERR_ECHO_TIMEOUT;

LAB_ERR_SYN_RECEIVE:
	close2(sComm);
	close2(sCtrl);
	*pnErrCode = XGetErrno();
	return ERR_SYN_RECEIVE;

LAB_ERR_SYN_SEND:
	close2(sComm);
	close2(sCtrl);
	*pnErrCode = XGetErrno();
	return ERR_SYN_SEND;
}


/***********************************************************************
 * FUNCTION:		XDeRegister() 
 * DESCRIPTION:  	Deregister the client on and close the socket of the connection to the STUNT server.
 * PARAMETERS:		
 *					->	sServerLog	The STUNT server socket. This socket must be gotten from XInit() and be valid.
 *					->	pchID		The client ID which will be deregistered from the STUNT server.
 *					<->	pnErrCode	Error code.
 * RETURNED:		
 *					ERR_NONE			Successful.
 *					ERR_CREATE_SOCKET	Fail to create a socket to the communication port.
 *					ERR_CONNECT			Fail to connect to the communication port of STUNT server. 
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XDeRegister(SOCKET sServerLog, CHAR* pchID, INT32* pnErrCode)
{
	//send message to the stunt server by communication thread to remove the client by ID
	Msg MsgDereg;
    INT32 nRetVal = 0;
	SOCKET sComm = (SOCKET) -1;
	struct sockaddr_in AddrComm;

	XInitSockAddr(&AddrComm, AF_INET, g_szServerIP1, SERVER_COMM_PORT, 0, 0);
	close2(sComm);
	//Create communication socket
	sComm = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
#ifdef _WIN32
	if (sComm == INVALID_SOCKET )
#else
	if (sComm == -1 )
#endif
	{
		close2(sComm);
		*pnErrCode = XGetErrno();
		return ERR_CREATE_SOCKET;
	}

	//Connect to the comm
	nRetVal = connect(sComm, (struct sockaddr *)&AddrComm, sizeof(AddrComm));
	if (nRetVal == -1) //SOCKET_ERROR 
	{
		close2(sComm);
		*pnErrCode = XGetErrno();
		return ERR_CONNECT;
	}

	//Write the Message sent to Communication server
	MsgDereg.nType = htonl(MSG_DEREGISTER);
	//ID of the client;
	strcpy(MsgDereg.Data.chID, pchID);
	//send the message
	send(sComm, (char*)&MsgDereg, sizeof(MsgDereg), 0);
	//close the socket
	close2(sServerLog);
	return ERR_NONE;
}

/************************************************************************************************************************/
/*			Private Function Definition																					*/
/************************************************************************************************************************/
/***********************************************************************
 * FUNCTION:		XAsymServer() 
 * DESCRIPTION:  	This function predicts the global port, exchanges the IP/PORT information through 
 *					STUNT server, and finally connects to the Asymmetric Client.
 * PARAMETERS:
 *					->	sServerLog	The STUNT server socket. This socket must be gotten from XInit() and be valid.
 *					->	sCtrl	A valid Control service socket of the STUNT server.
 *					<->	psListen	User specified listen socket. User should access this socket to 
 *									read/ write data if the process works successfully.
 *					<->	pAddrPeer	The address information of the connecting peer. Pass NULL if user 
 *									does not need this information.
 *					->	nTimeoutSec	The timeout will be set in all of the waiting procedures in this 
 *									function.
 *					<->	pnErrCode	Error code.
 * RETURNED:		
 *					ERR_NONE	Successful.
 *					ERR_PREDICT	Fail during port prediction. Check in XPredict().
 *					ERR_SEND	Fail to send public IP/PORT of the client.
 *					ERR_TIMEOUT	Timeout during waiting reading data from STUNT server.
 *					ERR_SELECT	SELECT fail during connecting to another peer.
 *					ERR_RECEIVE	Fail during receiving peer information or sync data from STUNT server.
 *					ERR_CONNECT	Fail to connect to the destination peer. 
 *					ERR_HAIRPIN	The public IP addresses of source and destination are the same.
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XAsymServer(SOCKET sServerLog, SOCKET sCtrl, SOCKET *psListen, struct sockaddr_in *pAddrPeer, INT32 nTimeoutSec, INT32* pnErrCode) 
{
    struct sockaddr_in AddrPeer, AddrClient, AddrGlobal;
    struct timeval Timeout;
    fd_set Socks;
    INT32 nOne = 0, nRetVal = 0;
	unsigned long ulOne = 0;

	//Using in macro by Saikat: 
	CHAR errbuf[256];
	SOCKET sock_logr = sServerLog;
	/////////////////////////////////////////////////////////////

	*psListen = (SOCKET) -1;
    
    strncpy(errbuf, "PORTPRED", 128);
    log_on_error(XPredict(sServerLog, psListen, &AddrGlobal, &AddrClient), "Predicting port", LAB_ERR_PREDICT);
    strncpy(errbuf, "CONTROL", 128);
    log_on_Xwrite_error(sCtrl, &AddrGlobal.sin_addr.s_addr, sizeof(AddrGlobal.sin_addr.s_addr), "Sending address", LAB_ERR_SEND);
    log_on_Xwrite_error(sCtrl, &AddrGlobal.sin_port, sizeof(AddrGlobal.sin_port), "Sending predicted port", LAB_ERR_SEND);

    AddrPeer.sin_family = AF_INET;
    readtimeout(sCtrl, Socks, nTimeoutSec, LAB_ERR_TIMEOUT);
    log_on_Xread_error(sCtrl, &AddrPeer.sin_addr.s_addr, sizeof(AddrPeer.sin_addr.s_addr), "Receiving address", LAB_ERR_RECEIVE);
    readtimeout(sCtrl, Socks, nTimeoutSec, LAB_ERR_TIMEOUT);
    log_on_Xread_error(sCtrl, &AddrPeer.sin_port, sizeof(AddrPeer.sin_port), "Receiving port", LAB_ERR_RECEIVE);
    readtimeout(sCtrl, Socks, nTimeoutSec, LAB_ERR_TIMEOUT);
    log_on_Xread_error(sCtrl, &nOne, sizeof(nOne), "Ready", LAB_ERR_RECEIVE);

	//HairPin Problem: do not process
	if (AddrGlobal.sin_addr.s_addr == AddrPeer.sin_addr.s_addr)
	{
		return ERR_HAIRPIN;
	}

	//Set psListen to non-blocking I/O
#ifdef _WIN32
	ulOne = 1;
	ioctlsocket(*psListen, FIONBIO, &ulOne);
#else
	fcntl(*psListen, F_SETFL, O_NONBLOCK);
#endif
	
	nRetVal = connect(*psListen, (struct sockaddr *)&AddrPeer, sizeof(AddrPeer));

	if (nRetVal == -1)
	{	
		*pnErrCode = XGetErrno();
#ifdef _WIN32
		if (*pnErrCode != WSAEWOULDBLOCK)	//would block
#else
		if (*pnErrCode != 115) //would block
#endif
			return ERR_CONNECT;
	}

	FD_ZERO(&Socks);
	FD_SET(*psListen, &Socks);
	Timeout.tv_sec = nTimeoutSec;
	Timeout.tv_usec = 0;
	//waiting user set timeout, this value MUST be the same as setting in XAsmClient.
	nRetVal = ::select(((INT32)*psListen) + 1, NULL, &Socks, NULL, &Timeout); 
	if (nRetVal == 0 || nRetVal == -1) //Timeout or SOCKET_ERROR
	{
		*pnErrCode = XGetErrno();
		return ERR_SELECT;
	}
	else
	{
		if (pAddrPeer != NULL)
		{
			pAddrPeer->sin_addr.s_addr = AddrPeer.sin_addr.s_addr;
			pAddrPeer->sin_port = AddrPeer.sin_port;
		}
		return ERR_NONE;
	}

LAB_ERR_PREDICT:
	return ERR_PREDICT;
LAB_ERR_SEND:
	*pnErrCode = XGetErrno();
	return ERR_SEND;
LAB_ERR_TIMEOUT:
	*pnErrCode = XGetErrno();
	return ERR_TIMEOUT;
LAB_ERR_RECEIVE:
	*pnErrCode = XGetErrno();
	return ERR_RECEIVE;

}

/***********************************************************************
 * FUNCTION:		XAsymClient() 
 * DESCRIPTION:  	This function predicts the global port, exchanges the IP/PORT information through 
 *					STUNT server, tries to connect to the destination peer, theoretically gets a failure,
 *					 listens to the Asymmetric Server and finally establishes the connection.
 * PARAMETERS:		
 *					->	sServerLog	The STUNT server socket. This socket must be gotten from XInit() and be valid.
 *					->	sCtrl	A valid Control service socket of the STUNT server.
 *					<->	psConnect	User specified connection socket.
 *					<->	pAddrPeer	The address information of the connecting peer. Pass NULL if 
 *									user does not need this information.
 *					->	nTimeoutSec	The timeout will be set in all of the waiting procedures in 
 *									this function.
 *					<->	pnErrCode	Error code.
 * RETURNED:
 *					ERR_NONE	Successful.
 *					ERR_PREDICT	Fail during port prediction. Check in XPredict().
 *					ERR_SEND	Fail to send public IP/PORT of the client.
 *					ERR_TIMEOUT	Timeout during waiting reading data from STUNT server.
 *					ERR_SELECT	SELECT fail during connecting to another peer.
 *					ERR_RECEIVE	Fail during receiving peer information or sync data from STUNT server.
 *					ERR_CONNECT	Fail to connect to the destination peer. 
 *					ERR_HAIRPIN	The public IP addresses of source and destination are the same.
 *					ERR_TRYCONNECT	XTryConnect() returned ERR_NONE, but it represents that the function should return back failure.
 *					ERR_CREATE_SOCKET	Fail to create a new socket.
 *					ERR_SETSOCKOPT	Fail to set socket option.
 *					ERR_BIND	Fail to bind a new socket.
 *					ERR_LISTEN	Fail to listen.
 *					ERR_ASYM_TIMEOUT	Timeout during waiting the connection from AsymServer.
 *					ERR_ACCEPT	Fail to accept.
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XAsymClient(SOCKET sServerLog, SOCKET sCtrl, SOCKET *psConnect, struct sockaddr_in *pAddrPeer, INT32 nTimeoutSec, INT32* pnErrCode) 
{
    struct sockaddr_in AddrGlobal;
    struct sockaddr_in AddrPeer;
    struct sockaddr_in AddrClient;
#ifdef _WIN32
	INT32 nAddrLen = sizeof(AddrPeer);
#else
	socklen_t nAddrLen = sizeof(AddrPeer);
#endif
	struct timeval Timeout;
    fd_set Socks;
    INT32 nOne = 1;
	SOCKET sAuxServer = (SOCKET)-1;

	//Using in macro by Saikat: 
	CHAR errbuf[256];
	SOCKET sock_logr = sServerLog;
	/////////////////////////////////////////////////////////////
	//Initialize socket psConnect
	*psConnect = (SOCKET)-1;

    strncpy(errbuf, "PORTPRED", 128);
    log_on_error(XPredict(sServerLog, &sAuxServer, &AddrGlobal, &AddrClient), "Predicting port", LAB_ERR_PREDICT);
    strncpy(errbuf, "CONTROL", 128);
    log_on_Xwrite_error(sCtrl, &AddrGlobal.sin_addr.s_addr, sizeof(AddrGlobal.sin_addr.s_addr), "Sending address", LAB_ERR_SEND);
    log_on_Xwrite_error(sCtrl, &AddrGlobal.sin_port, sizeof(AddrGlobal.sin_port), "Sending predicted port", LAB_ERR_SEND);

    AddrPeer.sin_family = AF_INET;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -