首页
社区
课程
招聘
[求助]ZXPortMap 端口映射项目求助
发表于: 2014-2-20 23:10 5197

[求助]ZXPortMap 端口映射项目求助

2014-2-20 23:10
5197
这个代码是Google找出来的,看上去没什么问题。
在公网IP上执行  PortTransfer ctrlPort ServerPort
然后再内网IP执行 PortTransfer ctrlIP ctrlPort Dest_IP Port

有很多内网IP端,但是只有一个公网IP。
我每次在公网IP上执行的端口都不一样,每一个端口对应一个内网IP。
开始是很正常。。但是我开了几十个映射连接之后。大概半小时后,
公网IP的机器就断网了。。。实在找不出为什么。。求助了


/*
端口映射
PortTransfer_三种模式。
(1) PortTransfer Port Dest_IP Port
在运行本程序的计算机上监听Port端口,并将所有连接请求转到Dest_IP的Port去
(2) PortTransfer ctrlIP ctrlPort Dest_IP Port
和模式3配合用,程序将先主动连接ctrlIP:ctrlPort,之后所有在模式3的ServerPort端口的请求转到Dest_IP:Port去
(3) PortTransfer ctrlPort ServerPort
在执行模式2前先执行,将监听ctrlPort和ServerPort 端口,ctrlPort供模式2使用,ServerPort提供服务.
模式1适合在网关上运行,将内网IP的端口映射到网关上,
如:PortTransfer 88 192.168.0.110 80
那么网关将开启88端口,所有在88端口的请求将转到内网的192.168.0.110的80端口
模式2和模式3联合使用可以将内网的IP和端口映射到指定的IP和端口上,
一般在公网IP(假设61.1.1.1)上执行模式3,如:PortTransfer 99 80, 80是映射过来的端口
内网用户执行模式2如:PortTransfer 61.1.1.1 99 127.0.0.1 80,
那么程序在内网将先连接61.1.1.1:99建立个连接,并等待接收命令。
之后当61.1.1.1的80端口有请求,将通过99端口命令内网机子和公网机子建立条新的数据连接,
并将请求通过新建的连接将请求转发到内网机.


  #include <WINSOCK2.H>
  #include <windows.h>
  #include <stdio.h>
  #pragma comment(lib, "ws2_32.lib")

  #define SERVERNAME "ZXPortMap"
  #define VERSION "v1.0"

  #define MAXBUFSIZE 8192
  #define ADDRSIZE 32

  HWND  mainwindowHWND;
  UINT  WM;
  DWORD BhSocket;

  struct SOCKINFO
  {
  SOCKET ClientSock;
  SOCKET ServerSock;
  };
  struct ADDRESS
  {
  char szIP[ADDRSIZE];
  WORD wPort;
  SOCKET s;
  };

  ////////A simple class of stack operator. code start.....
  template<typename T>
  class STACK
  {
  #define MAXSTACK 1024*2

  private:
  int top;
  T Data[MAXSTACK];
  public:

  STACK()
  {
  top = -1;
  }

  bool IsEmpty()
  {
  return top < 0;
  }

  bool IsFull()
  {
  return top >= MAXSTACK;
  }

  bool Push(T data)
  {
  if(IsFull())
  return false;
  top++;
  Data[top] = data;
  return true;
  }

  T Pop()
  {
  return Data[top--];
  }

  };/////////////////////stack end
  //////////////////////////////////////////////////////////////////Transfer  some Parameters
  template<typename X, typename Y>
  class TransferParam
  {
  public:
  X GlobalData;
  STACK<Y> LocalData;
  public:
  TransferParam();
  virtual ~TransferParam();
  bool Push(Y data);
  Y Pop();

  };

  template<typename X, typename Y>
  TransferParam<X, Y>::TransferParam()
  {
  memset(this, 0, sizeof(TransferParam));
  }

  template<typename X, typename Y>
  TransferParam<X, Y>::~TransferParam()
  {

  }

  template<typename X, typename Y>
  bool TransferParam<X, Y>::Push(Y data)
  {
  return LocalData.Push(data);
  }

  template<typename X, typename Y>
  Y TransferParam<X, Y>::Pop()
  {
  return LocalData.Pop(data);
  }
  ///////////////////////////////////////////////////

  int nTimes = 0;

  int DataSend(SOCKET s, char *DataBuf, int DataLen)//将DataBuf中的DataLen个字节发到s去
  {
	  int nBytesLeft = DataLen;
	  int nBytesSent = 0;
	  int ret;
	  //set socket to blocking mode
	  int iMode = 0;
	  ioctlsocket(s, FIONBIO, (u_long FAR*) &iMode);
	  while(nBytesLeft > 0)
	  {
		  ret = send(s, DataBuf + nBytesSent, nBytesLeft, 0);
		  if(ret <= 0)
		  break;
		  nBytesSent += ret;
		  nBytesLeft -= ret;
	  }
	  return nBytesSent;
  }

  DWORD WINAPI TransmitData(LPVOID lParam)//在两个SOCKET中进行数据转发
  {
	  SOCKINFO socks = *((SOCKINFO*)lParam);
	  SOCKET ClientSock = socks.ClientSock;
	  SOCKET ServerSock = socks.ServerSock;
	  char RecvBuf[MAXBUFSIZE] = {0};
	  fd_set Fd_Read;
	  int ret, nRecv;

	  while(1)
	  {
		  FD_ZERO(&Fd_Read);
		  FD_SET(ClientSock, &Fd_Read);
		  FD_SET(ServerSock, &Fd_Read);
		  ret = select(0, &Fd_Read, NULL, NULL, NULL);
		  if(ret <= 0)
			  goto error;
		  if(FD_ISSET(ClientSock, &Fd_Read))
		  {
			  nRecv = recv(ClientSock, RecvBuf, sizeof(RecvBuf), 0);
			  if(nRecv <= 0)
				  goto error;
			  ret = DataSend(ServerSock, RecvBuf, nRecv);
			  if(ret == 0 || ret != nRecv)
				  goto error;
		  }
		  if(FD_ISSET(ServerSock, &Fd_Read))
		  {
			  nRecv = recv(ServerSock, RecvBuf, sizeof(RecvBuf), 0);
			  if(nRecv <= 0)
			  goto error;
			  ret = DataSend(ClientSock, RecvBuf, nRecv);
			  if(ret == 0 || ret != nRecv)
			  goto error;
		  }
	  }
	  error:
	  closesocket(ClientSock);
	  closesocket(ServerSock);
	  nTimes--;
	  return 0;
  }

  SOCKET ConnectHost(DWORD dwIP, WORD wPort)//连接指定IP和端口
  {
	  SOCKET sockid;

	  if ((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
	  return 0;
	  struct sockaddr_in srv_addr;
	  srv_addr.sin_family = AF_INET;
	  srv_addr.sin_addr.S_un.S_addr = dwIP;
	  srv_addr.sin_port = htons(wPort);
	  if (connect(sockid,(struct sockaddr*)&srv_addr,sizeof(struct sockaddr_in)) 
	  == SOCKET_ERROR)
	  goto error;
	  return sockid;
	  error:
	  closesocket(sockid);
	  return 0;
  }

  SOCKET ConnectHost(char *szIP, WORD wPort)
  {
	return ConnectHost(inet_addr(szIP), wPort);
  }

  SOCKET CreateSocket(DWORD dwIP, WORD wPort)//在dwIP上绑定wPort端口
  {
	  SOCKET sockid;

	  if ((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)
	  return 0;
	  struct sockaddr_in srv_addr = {0};
	  srv_addr.sin_family = AF_INET;
	  srv_addr.sin_addr.S_un.
	  S_addr = dwIP;
	  srv_addr.sin_port = htons(wPort);
	  if (bind(sockid,(struct sockaddr*)&srv_addr,sizeof(struct sockaddr_in)) == 
	  SOCKET_ERROR)
	  goto error;
	  listen(sockid,3);
	  return sockid;
	  error:
	  closesocket(sockid);
	  return 0;
  }

  SOCKET CreateTmpSocket(WORD *wPort)//创建一个临时的套接字,指针wPort获得创建的临时端口
  {
	  struct sockaddr_in srv_addr = {0};
	  int addrlen = sizeof(struct sockaddr_in);

	  SOCKET s = CreateSocket(INADDR_ANY, 0);
	  if(s <= 0)
	  goto error;

	  if(getsockname(s, (struct sockaddr*)&srv_addr, &addrlen) == SOCKET_ERROR)
	  goto error;
	  *wPort = ntohs(srv_addr.sin_port);
	  return s;
	  error:
	  closesocket(s);
	  return 0;
  }

  BOOL InitSocket()
  {
	  WSADATA wsadata;
	  return WSAStartup(MAKEWORD(2,2),&wsadata) == 0;
  }

  DWORD WINAPI PortTransfer_3(LPVOID lParam)
  {
	  SOCKINFO socks;
	  SOCKET ClientSocket, ServerSocket, CtrlSocket, tmpSocket;
	  TransferParam<SOCKET, SOCKET> *ConfigInfo = (TransferParam<SOCKET, 
	  SOCKET>*)lParam;
	  CtrlSocket = ConfigInfo->GlobalData;
	  ClientSocket = ConfigInfo->LocalData.Pop();

	  WORD wPort;
	  tmpSocket = CreateTmpSocket(&wPort);//创建个临时端口

	  if(tmpSocket <= 0 || wPort <= 0)
	  {
		  closesocket(ClientSocket);
		  SendMessage( mainwindowHWND,WM,30,BhSocket);
		  return 0;
	  }
	  //通知内网用户发起新的连接到刚创建的临时端口
	  if(send(CtrlSocket, (char*)&wPort, sizeof(wPort), 0) == SOCKET_ERROR)
	  {
			closesocket(ClientSocket);
			closesocket(CtrlSocket);
			SendMessage( mainwindowHWND,WM,31,BhSocket);
			return 0;
	  }
	  printf("ThreadID: %d ==> Waiting for server connection...", nTimes);
	  ServerSocket = accept(tmpSocket, NULL, NULL);
	  if(ServerSocket == INVALID_SOCKET)
	  {
		  printf("Error.\r\n");
		  closesocket(ClientSocket);
		  SendMessage( mainwindowHWND,WM,32,BhSocket);
		  return 0;
	  }
	  printf("OK.\r\n");
	  socks.ClientSock = ClientSocket;
	  socks.ServerSock = ServerSocket;
	  //进入纯数据转发状态
	  return TransmitData((LPVOID)&socks);
  }

  BOOL PortTransfer_3(WORD wCtrlPort, WORD wServerPort)//监听的两个端口
  {
	  printf("进入 PortTransfer_3 port1=%u  port2=%u \r\n", wCtrlPort,wServerPort);
	  HANDLE hThread;
	  DWORD dwThreadId;
	  BOOL bOptVal = TRUE;
	  int bOptLen = sizeof(BOOL);
	  TransferParam<SOCKET, SOCKET> ConfigInfo;
	  SOCKET ctrlsockid, serversockid, CtrlSocket, AcceptSocket;

	  ctrlsockid = CreateSocket(INADDR_ANY, wCtrlPort);//创建套接字
	  if(ctrlsockid <= 0)
	  {
	  	  SendMessage( mainwindowHWND,WM,20,BhSocket);
		  goto error2;
	  }
	  serversockid = CreateSocket(INADDR_ANY, wServerPort);//创建套接字
	  if(serversockid <= 0)
	  {
	  	  SendMessage( mainwindowHWND,WM,21,BhSocket);
		  goto error1;
	  }

	  printf("接受 来自B的 连接...");
	  CtrlSocket = accept(ctrlsockid, NULL, NULL);//接受来自(内网用户发起)PortTransfer_2模式建立控制管道连接的请求
	  if(CtrlSocket == INVALID_SOCKET)
	  {
	  	  SendMessage( mainwindowHWND,WM,22,BhSocket);
		  goto error0;
	  }
	  //setsockopt( keep-alive......
	  if (setsockopt(CtrlSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&bOptVal, bOptLen) == SOCKET_ERROR) 
	  {
	  	  SendMessage( mainwindowHWND,WM,23,BhSocket);
		  goto error0;
		  //printf("Set SO_KEEPALIVE: ON\n");
	  }
	  printf("OK\r\n");
	  //与内网用户建立了连接后就相当端口映射成功了
	  //准备进入接收服务请求状态,并将在新起的线程中通过控制管道通知内网用户发起新的连接进行数据转发
	  ConfigInfo.GlobalData = CtrlSocket;
	  while(1)
	  {
		  //printf("Accepting new Client...\r\n");
		  printf("接受 来自B的 请求...");
		  AcceptSocket = accept(serversockid, NULL, NULL);
		  if(AcceptSocket == INVALID_SOCKET)
		  {
		  	  SendMessage( mainwindowHWND,WM,24,BhSocket);
			  printf("Error.\r\n");
			  Sleep(1000);
			  continue;
		  }
		  nTimes++;
			printf("OK 为一个请求建立一个转发线程.\r\n");
			ConfigInfo.LocalData.Push(AcceptSocket);//把接受到的套接字Push到栈结构中,传到新起线程那边可以再Pop出来
			hThread = CreateThread(NULL, 0, PortTransfer_3, (LPVOID)&ConfigInfo, NULL, &dwThreadId);
		  if(hThread)
			  CloseHandle(hThread);
		  else
			  Sleep(1000);
	  }

	  error0:
		  closesocket(CtrlSocket);
	  error1:
		  closesocket(serversockid);
	  error2:
		  closesocket(ctrlsockid);
	  return false;
  }

  void Usage(char *ProName)
  {
  printf (SERVERNAME" "VERSION" " "By LZX.\r\n");
  printf ("Usage:\r\n"
  " %s ctrlPort ServerPort\r\n"
  " %s Port Dest_IP Port\r\n"
  " %s ctrlIP ctrlPort Dest_IP Port\r\n", ProName, ProName, ProName);
  }

  int main(int argc, char **argv)
  {
	  if(argc !=6)
		  return 0;
	  mainwindowHWND=(HWND)atoi(argv[1]);
	  WM=atoi(argv[2]);
	  BhSocket=atol(argv[3]);
	  if(! InitSocket())
	  {
		  SendMessage( mainwindowHWND,WM,1,BhSocket);
		  return 0;
	  }
	  else
	  {
		  PortTransfer_3(atoi(argv[4]), atoi(argv[5]));
		  WSACleanup();
		  return 0;
	  }
	  SendMessage( mainwindowHWND,WM,100,BhSocket);
	  WSACleanup();
	  return 0;

  }



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 248
活跃值: (1106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看看代理服务端的有关资料。
2014-2-21 08:52
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
顶盾盾。。。。。对网络编程生疏,帮不上啥忙
2014-2-21 10:34
0
雪    币: 131
活跃值: (98)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
少开几个,也断网么?
2014-2-21 12:13
0
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
5
少开几个,也断网么?  少开几个也会断网
2014-2-22 08:42
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
还是调试一下吧,,
2014-2-24 13:56
0
游客
登录 | 注册 方可回帖
返回
//