// NatCheck.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <process.h>
#include <stdio.h>
#include <afx.h>
#include "winsock2.h"
#include "./Include/packet.h"
#pragma comment(lib,"./lib/wininet.lib")
#pragma comment(lib,"wsock32.lib")
#include "ws2tcpip.h"
#include "string.h"
#define N_SuperNode 5
#define N_NatCheckRequestQueue 20
#define PORT_SERVER_NATCHECK 8888
#define PORT_SERVER_NATCHECK_1 8889
#define PORT_CLIENT_NATCHECK 7777
#define PORT_SERVER_CLIENT_INFO 4444
#define N_CheckTime 5 //最多检测次数
SOCKET sClient,sServer;//客户端和服务端的socket号
struct sockaddr_in sn1_addr,sn2_addr,sn_addr,client_addr;
struct sockaddr_in client_addr_deal;
struct in_addr in_addr_tmp,in_addr_tmp1;
FILE *fp; //客户端读取hostcache.txt文件指针
int i=0,j=0;
unsigned long int snIP[N_SuperNode];//读取的SN的IP地址列表
unsigned short int snPort[N_SuperNode];//读取的SN的Port列表
char tmpIP[15],tmpPort[5];
char ch;
char IP_return[15];
/* 本client的网络类型:
* 0 = public net
* 1 = full cone nat
* 2 = symmetric nat
* 3 = restricted cone nat
* 4 = port restricted cone nat
*/
unsigned long int myID=0,friendID=26;//本client和friend的用户ID
char myNetType=-1,friendNetType=-1;
unsigned long int myPubIp,friendPubIp,myPriIp,friendPriIp;
unsigned short int myPubPort,friendPubPort,myPriPort,friendPriPort;
//natCheck请求包结构
struct natCheckPacket{
char version;
char dowhat;
unsigned short int port;
unsigned long int ip;
unsigned long int id;
}natCheckPacket;
typedef struct natCheckPacket NCP;
char buff[sizeof(natCheckPacket)];//发包用的缓冲区
//natCheck请求数据结构
struct natCheckRequest{
NCP ncp;//缓存到来的请求包
struct natCheckRequest * next;//指向下一个请求数据
unsigned long int ip;//发送请求的client IP地址
unsigned short int port;//发送请求的client Port
}natCheckRequest;
typedef struct natCheckRequest NCR;
struct netInfoResponsePacket{
NCP ncp;
unsigned long int ip_pub;
unsigned short int port_pub;
unsigned short int no;
}netInfoResponsePacket;
typedef struct netInfoResponsePacket NIRP;
//natCheck请求数据循环队列
NCR natCheckRequestQueue[N_NatCheckRequestQueue];
NCR * h_NatCheckRequestQueue,* t_NatCheckRequestQueue;
/*
* 获得本地主机IP地址
*/
char * getownIP()
{
//
// 获得主机名.
char hostname[256];
int res = gethostname(hostname, sizeof(hostname));
if (res != 0) {
printf("Error: %u/n", WSAGetLastError());
return "failed";
}
// 根据主机名获取主机信息.
hostent* pHostent = gethostbyname(hostname);
if (pHostent==NULL) {
printf("Error: %u/n", WSAGetLastError());
return "failed";
}
//
// 解析返回的hostent信息.
hostent& he = *pHostent;
sockaddr_in sa;
memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[0],he.h_length);
return inet_ntoa(sa.sin_addr);
}
unsigned long int getownIP_uli()
{
//
// 获得主机名.
char hostname[256];
int res = gethostname(hostname, sizeof(hostname));
if (res != 0) {
printf("Error: %u/n", WSAGetLastError());
return -1;
}
// 根据主机名获取主机信息.
hostent* pHostent = gethostbyname(hostname);
if (pHostent==NULL) {
printf("Error: %u/n", WSAGetLastError());
return -1;
}
//
// 解析返回的hostent信息.
hostent& he = *pHostent;
sockaddr_in sa;
memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[0],he.h_length);
return sa.sin_addr.S_un.S_addr;
}
/*
* superNode接收请求线程入口函数
*/
unsigned int _stdcall ThreadFunction_sn_get(void *param)
{
//创建套接字
if( (sServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
{
printf("获取SOCKET号失败!!!/n");
return 0;
}
//绑定套接字和本机地址和端口
sn_addr.sin_family=AF_INET;
sn_addr.sin_port=htons(PORT_SERVER_NATCHECK);
sn_addr.sin_addr.s_addr =INADDR_ANY ;//inet_addr(getownIP()); //
if(bind(sServer, (struct sockaddr*)&sn_addr, sizeof(sn_addr)) < 0 )
{
printf("不能将服务器地址捆绑到SOCKET号上!!!/n");
closesocket(sServer);
return 0;
}
//printf("接收..../n");
int iLen=sizeof(client_addr);
struct natCheckPacket * ncp=(struct natCheckPacket *)buff;
int timeout=300;
while (1)
{
setsockopt(sServer, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,sizeof(timeout));
if(recvfrom(sServer,buff,sizeof(buff),0,(sockaddr*)&client_addr,&iLen)!=-1)
{
//判断队列是否满
if(t_NatCheckRequestQueue->next!=h_NatCheckRequestQueue)
{
//先修改t
NCR * t=t_NatCheckRequestQueue;
t_NatCheckRequestQueue=t->next;
//再写入
t->ncp=*(ncp);
t->ip=client_addr.sin_addr.S_un.S_addr;
t->port=client_addr.sin_port;
}
}
Sleep(300);
//printf("version:%d/tdowhat:%d/tport:%d/tip:%d/n",ncp->version,ncp->dowhat,
// ncp->port,ncp->ip);
//printf("Client said: %s/n",buff);
//strcpy(buff,"I am a server!!/n");
//sendto(sServer,buff,sizeof(buff),0,(sockaddr*)&client_addr,sizeof(client_addr));
}
//closesocket(sServer);
return 0;
}
/*
* 构造NCP包发送给SuperNode
* 接受返回的NCP包
*/
int sendNCPtoSNandRecvNCP(unsigned long int ip_SN,unsigned short int port_SN,
NCP ncp_send)
{
int timeout=300;
sn_addr.sin_addr.S_un.S_addr=ip_SN;
sn_addr.sin_family=AF_INET;
sn_addr.sin_port=htons(port_SN);
int iLen=sizeof(sn_addr);
NCP * ncp=(NCP *)buff;
ncp->version=ncp_send.version;
ncp->dowhat=ncp_send.dowhat;
ncp->port=ncp_send.port;
ncp->ip=ncp_send.ip;
ncp->id=ncp_send.id;
setsockopt(sClient, SOL_SOCKET , SO_SNDTIMEO, (char *)&timeout,sizeof(timeout));
sendto(sClient,buff,sizeof(buff),0,(SOCKADDR*)&sn_addr,iLen);
in_addr_tmp.S_un.S_addr=ip_SN;
i