TryClient.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:5k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * 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;
- }
- }