📄 tryclient.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 + -