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

📄 tryclient.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
字号:
/*
 *  Openmysee
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
// TryClient.cpp: implementation of the TryClient class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TryClient.h"
#include "Communicator.h"

namespace NPLayer1 {
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

TryClient::TryClient(Communicator* c) : comm(c) {}

TryClient::~TryClient() {}

void TryClient::Try() {
	// 尝试连接可以连接的Peer,直到没有可供连接的Peer
	for(;;) {
		// 获取可以连接的Peer地址
		ConnectingPeer tryPeer;
		if(!comm->p2pMgr.GetPeer4Connect(tryPeer)) {
			break;	// 无可连接
		}

		tryPeer.isSameLan = false;
		if(tryPeer.IsNAT()) {
			if(tryPeer.outerIP.sin_addr.s_addr == comm->localAddress.outerIP.sin_addr.s_addr) {
				//与本机在同一个内网中,直接连接其内网IP
				tryPeer.isSameLan = true;
			}
		}

		CONNECT_RESULT ret = Connecting(tryPeer, tryPeer.sock);

		// 记录连接时间
		tryPeer.connectTime = timeGetTime();

		if(ret == CR_CONNECTED)
			comm->p2pMgr.AddP2PClient(tryPeer);
		else if(ret == CR_WOULDBLOCK) {
			comm->p2pMgr.AddConnecting(tryPeer);
		}
		else if(ret == CR_ERROR)
			comm->p2pMgr.AddBadAddr(tryPeer);
	}
}

CONNECT_RESULT TryClient::Connecting(P2PAddress addr, SOCKET& sock) {
	NormalAddress tmpAddr;
	tmpAddr.sin_addr.s_addr = addr.outerIP.sin_addr.s_addr; // outer ip
	tmpAddr.sin_port = addr.subnetIP.sin_port; // serv Port

	if(addr.IsNAT()) {
		if(addr.outerIP.sin_addr.s_addr == comm->localAddress.outerIP.sin_addr.s_addr) {
			//与本机在同一个内网中,直接连接其内网IP
			tmpAddr.sin_addr.s_addr = addr.subnetIP.sin_addr.s_addr; // subnet ip
		}
		else {
			comm->logFile.StatusOut("不能连接其他内网中的客户端。%s", comm->p2pMgr.FormatIPAddress(addr));
			return CR_ERROR;
		}
	}

	return Connecting(tmpAddr, sock);
}

CONNECT_RESULT TryClient::Connecting(NormalAddress addr, SOCKET& sock) {
	comm->logFile.StatusOut("Connecting to %s:%d.", 
		inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));

	CONNECT_RESULT ret = CR_ERROR;

	// Create a TCP/IP socket that is bound to the server.
	// Microsoft Knowledge Base: WSA_FLAG_OVERLAPPED Is Needed for Non-Blocking Sockets
	// http://support.microsoft.com/default.aspx?scid=kb;EN-US;179942
	sock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if(sock == INVALID_SOCKET) {
		comm->logFile.StatusErr("Creating socket", WSAGetLastError());
		return ret;
	}

	// SO_EXCLUSIVEADDRUSE is only supported in 2000/XP/2003 and higher OS.
	if(comm->osvi.dwMajorVersion > 5) {
		// 独占端口
		BOOL bExAddrUse = TRUE;
		if(setsockopt(sock, SOL_SOCKET, ((int)(~SO_REUSEADDR)), (const char*)&bExAddrUse, sizeof(bExAddrUse)) == SOCKET_ERROR) {
			comm->logFile.StatusErr("Setting socket as SO_EXCLUSIVEADDRUSE", WSAGetLastError());
			return ret;
		}
	}

	// 不使用Nagle算法
	BOOL bNoDelay = TRUE;
	if(setsockopt(sock, SOL_SOCKET, TCP_NODELAY, (const char*)&bNoDelay, sizeof(bNoDelay)) == SOCKET_ERROR) {
		comm->logFile.StatusErr("Setting UDP socket as TCP_NODELAY", WSAGetLastError());
		return ret;
	}

	// Set this socket as a Non-blocking socket.
	ULONG flag = 1;
	if(ioctlsocket(sock, FIONBIO, &flag) == SOCKET_ERROR) {
		comm->logFile.StatusErr("Setting socket as non-blocking", WSAGetLastError());
		return ret;
	}

	// Connect to remote address
	if(WSAConnect(sock, 
		(sockaddr*)&addr, sizeof(sockaddr), 
		NULL, NULL, NULL, NULL) == SOCKET_ERROR) {
			if(WSAGetLastError() != WSAEWOULDBLOCK) {
				comm->logFile.StatusErr("Connecting socket", WSAGetLastError());
				return ret;
			}
			else {
				ret = CR_WOULDBLOCK;
				comm->logFile.StatusOut("%s:%d is blocking.", 
					inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
			}
		}
	else {
		ret = CR_CONNECTED;
		comm->logFile.StatusOut("%s:%d is connected.", 
			inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
	}
	return ret;
}
}

⌨️ 快捷键说明

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