TCP to TCP 数据转发

目的
    我们部门在内网有一台Web服务器A,用于部门文档信息管理,可分公司的员工,或出差的员工,都不能直接访问这台机器。
所以还得把发邮件来完成文档的提交。如何实现外地员工能访问Web服务器A呢?公司有一台可以访问外网的机器B,要是在B上运行
一个数据转发程序,固定地把外网发送到某个端口的数据转发到A上的Web端口,同时把A上回送的数据转发出去,不就一切OK了吗!


设计
//主程序
Main()
{
   beginthread(Main Thread());
}

//主线程
Main Thread(Param)
{
   创建"本地监听SOCK"
   while(true)
   {
      等待客户端连接
      等到后,创建"目标SOCK"
      连接到目的地
      连接成功后,创建"Wait Thread"
   }
}
//Wait 线程 
Wait Thread(Param)
{
  创建"连接SOCK"->"目标SOCK"数据转发Thread
  创建"目标SOCK"->"连接SOCK"数据转发Thread
  等待这两个线程结束
  释放SOCK资源
}
//TCP2TCP数据转发线程
TCP2TCP Thread(Param)
{
   SOCK FROM,TO
   while(read  >0)
   {
 read(From,Buff);
 Send(To,Buff);
   }
}

参考代码
参数结构
struct AGENTGATEWAYINFO{
 int  LocalPort;  //本地Port
 int  TargetPort;  //目标Port
 int  TargetPort1; //目标Port2
 char TargetIP[64]; //目标IP
 
 char SpecialIP[64]; //特定的IP
 int  SpecialTargetPort;//特定的目标port
 char SpecialTargetIP[64];//特定的目标IP

 int  ProxyType;  //代理类型
 char ProxyIP[30]; //代理IP
 int  ProxyPort;  //代理端口
 char ProxyUser[50]; //代理用户
 char ProxyPassword[50];//代理密码
};
//主线程
DWORD mainthread(LPVOID lpvoid)
{
 //获取传人的参数
 AGENTGATEWAYINFO *psi = (AGENTGATEWAYINFO *)lpvoid;
 AGENTGATEWAYINFO  si;
 memcpy(&si,psi,sizeof(AGENTGATEWAYINFO));
 SOCKET listensock,sock[2];
 unsigned long hostip;
 char chostip[64]="0";
 delete psi;

 printf("/n************Start Agent Tcp GateWay %d==>%s:%d****************",si.LocalPort,si.TargetIP,si.TargetPort);
 psi = NULL;
 hostip=inet_addr(chostip);
 //先建立本地监听socket,用来等待需要转发的连接
 if((listensock = socket(AF_INET,SOCK_STREAM,0)) == NULL)
 {
  printf("/nTcpGateWay:Can't create incoming socket./n");
  return -1;
 }
 sockaddr_in incomingsin;
 incomingsin.sin_family = AF_INET;
 incomingsin.sin_port = htons(si.LocalPort);
 if(hostip!=INADDR_NONE)
 {
  incomingsin.sin_addr.s_addr=hostip;
 }
 else
 {
  printf("/nTcpGateWay:Can't look up local ip./n");
  return -1;
 }
 
 sockaddr_in clientaddr;
 int iclientaddr = sizeof(clientaddr);

 bind(listensock,(LPSOCKADDR)&incomingsin,sizeof(sockaddr));
 listen(listensock,10);
 printf("/nTcpGateWay:Listening at ip: %s , port: %d./n",inet_ntoa(incomingsin.sin_addr) , si.LocalPort);
 _AddSock(listensock);
 while (1)
 {
  //开始等待新的连接
  memset( &clientaddr, 0 , sizeof( clientaddr) );
  sock[0] = accept(listensock,(struct sockaddr *)&clientaddr,&iclientaddr);
  
  if(sock[0] == -1)
  {
   printf("client eq -1 ,break it!/n");
   Sleep(1000);
   continue;
  }
  else
  { //等到了
   SOCKETINFO *psgc = new SOCKETINFO();
   psgc->sock[0] = sock[0];
   strcpy(psgc->SockIP[0],inet_ntoa(clientaddr.sin_addr));
   psgc->SockPort[0] = ntohs(clientaddr.sin_port);
   printf("/nTcpGateWay:Incoming connection from %s:%d.",psgc->SockIP[0],psgc->SockPort[0]);

   strcpy(psgc->SockIP[1],si.TargetIP);
   psgc->SockPort[1] = si.TargetPort;
   //产生一个目标SOCK
   if((psgc->sock[1] = socket(AF_INET,SOCK_STREAM,0)) == NULL)
   {
    printf("/nTcpGateWay:Can't create sending socket.");
    delete psgc;
    continue;
   }
   CWSocket wsock0 ;
   wsock0.Attach(psgc->sock[1]);

   try
   { //通过代理连接目标
    switch(si.ProxyType)
    {
    case 1://SOCK4
      wsock0.ConnectViaSocks4(psgc->SockIP[1], psgc->SockPort[1],si.ProxyIP, si.ProxyPort);
     break;
    case 2://SOCK5
     if(strlen(si.ProxyUser) > 0)
     {
      wsock0.ConnectViaSocks5(psgc->SockIP[1], psgc->SockPort[1],si.ProxyIP, si.ProxyPort,
       si.ProxyUser,
       si.ProxyPassword);
     }else
     {
      wsock0.ConnectViaSocks5(psgc->SockIP[1], psgc->SockPort[1],si.ProxyIP, si.ProxyPort);
     }

     break;
    case 3://HTTP11
     {
      CString sProxyResponse;
      if(strlen(si.ProxyUser) > 0)
      {
       wsock0.ConnectViaHTTPProxy(psgc->SockIP[1], psgc->SockPort[1],si.ProxyIP, si.ProxyPort,
        sProxyResponse,
        si.ProxyUser,
        si.ProxyPassword);
      }else
      {
       wsock0.ConnectViaHTTPProxy(psgc->SockIP[1], psgc->SockPort[1],si.ProxyIP, si.ProxyPort,sProxyResponse);
      }
     }
     break;
    default:
     wsock0.Connect(psgc->SockIP[1],psgc->SockPort[1]);
     break;
    }
   }
   catch(CWSocketException* pEx)
   {
    pEx->Delete();
    wsock0.Detach();
    _DelSock(psgc->sock[1]);
    _DelSock(psgc->sock[0]);
    printf("/nTcpGateWay:Can't forward to %s:%d.",si.TargetIP,si.TargetPort);
    delete psgc;
    continue;
   }
   wsock0.Detach();
   printf("/n%s:%d ==> %s:%d./n",psgc->SockIP[0],psgc->SockPort[0],psgc->SockIP[1],psgc->SockPort[1]);
   DWORD threadid;
   //连接成功,创建监护线程,用来监控socket
   psgc->hWaitThread = CreateThread(NULL,0,waitthread,(LPVOID)psgc,NULL,&threadid);
   _AddThread(psgc->hWaitThread);
  }
 }
 _DelSock(listensock);
 return 0;
}
//监护线程,用来监控socket
DWORD waitthread(LPVOID lpvoid)
{
 SOCKETINFO *psgc  = (SOCKETINFO *)lpvoid;
 HANDLE hWaitThread = psgc->hWaitThread;
 _AddSock(psgc->sock[1]);
 _AddSock(psgc->sock[0]);
 //创建连接端->目的端数据转发线程
 psgc->hThreads[0] = CreateThread(NULL,0,tcp2tcp,(LPVOID)psgc,NULL,&psgc->id[0]);
 _AddThread(psgc->hThreads[0]);
 //创建目的端->连接端数据转发线程
 psgc->hThreads[1] = CreateThread(NULL,0,tcp2tcp,(LPVOID)psgc,NULL,&psgc->id[1]);
 _AddThread(psgc->hThreads[1]);
 //等待线程结束 
 DWORD  waiter;
 waiter = WaitForMultipleObjects(MAX_SOCKS,psgc->hThreads,FALSE,INFINITE);
 
 if(waiter == WAIT_OBJECT_0)
 {
  _DelThread(psgc->hThreads[0]);
  _DelSock(psgc->sock[0]);
  Sleep(50);
  _DelSock(psgc->sock[1]);
  WaitForSingleObject(psgc->hThreads[1],2000);
  _DelThread(psgc->hThreads[1]);

 }else if(waiter == WAIT_OBJECT_0+1)
 {
  _DelThread(psgc->hThreads[1]);
  _DelSock(psgc->sock[1]);
  Sleep(50);
  _DelSock(psgc->sock[0]);
  WaitForSingleObject(psgc->hThreads[0],2000);
  _DelThread(psgc->hThreads[0]);
 }else
 {
  _DelSock(psgc->sock[1]);
  Sleep(50);
  _DelSock(psgc->sock[0]);
  _DelThread(psgc->hThreads[1]);
  _DelThread(psgc->hThreads[0]);
 }
 printf("/n%s:%d Socket closed./n",psgc->SockIP[0],psgc->SockPort[0]);
 delete psgc;
 _PostDelThread(hWaitThread);
 ExitThread(0);
 return 0;
}
DWORD WINAPI tcp2tcp(LPVOID lpvoid)
{
 SOCKETINFO *psgc  = (SOCKETINFO *)lpvoid;
 DWORD threadid=GetCurrentThreadId();
 SOCKET s[2];
 HANDLE ReadEvent = NULL ;
 BOOL isFirstRead=TRUE;
 CString sHexDispData;
 BOOL bIsDisplay0 = TRUE;
 if(psgc->id[0] == threadid)
 {
  s[0] = psgc->sock[0];
  s[1] = psgc->sock[1];
  ReadEvent = psgc->ReadEvent[0];
 }else
 {
  s[1] = psgc->sock[0];
  s[0] = psgc->sock[1];
  ReadEvent = psgc->ReadEvent[1];
  bIsDisplay0 = FALSE;
 }
 printf("/n***New TCP2TCP Thread %d recv %d send %d./n",threadid,s[0],s[1]);
 char incomingbuff[maxsize];
 int read = 1;
 while(read  >0)
 {
  read  = recv(s[0],incomingbuff, maxsize,0);
  if(read <=0  ) break;

  printf("/nTCP2TCP Thread %d recv %d bytes.",threadid,read);
  int npos=0;
  while(npos < read)
  {
   int nsendcount = send(s[1],incomingbuff+npos,read-npos,0);
   if(nsendcount <= 0 ) return 0;
   printf("/nTCP2TCP Thread %d send %d bytes.",threadid,nsendcount);
   npos += nsendcount;
  }
 }
 printf("/nTCP2TCP Thread %d LastError %d",threadid,GetLastError());
 return 0;
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值