CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  网络编程

Socket编程,如何通过代理连接互联网上的服务器?

楼主yang79tao()2005-02-25 19:10:23 在 VC/MFC / 网络编程 提问

我写了个服务器,用的是MFC的CSocket,当服务器和客户端同在一个局或网,或都在公网上,都可以成功连接,但如果服务器在公网上,客户端在局域网,局域网通过代理上网,这个时候就连接不上了。请问有没有办法解决? 问题点数:50、回复次数:15Top

1 楼yang79tao()回复于 2005-02-25 21:34:32 得分 0

dingTop

2 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-02-26 08:53:07 得分 0

要看你是TCP连接,还是UDP连接,是http代理、socks5代理,还是什么其他的。Top

3 楼yang79tao()回复于 2005-02-26 09:38:06 得分 0

TCP连接,http代理、socks5代理均可,两者都有。Top

4 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-02-26 10:39:06 得分 0

客户端程序是你写的吗?如果不是,代理相对与服务器应该是透明的,一般不会出现不用代理能够连上,用代理连不上的问题,建议你跟踪一下代码,以便发现连不上的具体原因。Top

5 楼chenjieread(苦学VC++中...)回复于 2005-02-26 10:39:47 得分 0

呵呵,很感兴趣啊!!!大家继续讨论哦Top

6 楼yang79tao()回复于 2005-02-26 15:49:16 得分 0

情况是这样的:  
  客户和服务器端都是我写的,服务器端放在公网上,客户端放在通过代理能上外网的某局域网的一台机器上,客户端连接不上服务器。我回去看看返回的错误代码吧。Top

7 楼yang79tao()回复于 2005-02-26 19:01:41 得分 0

错误代码当然是:WSAEHOSTUNREACH,解释为:no   route   to   host,  
  我想这样的情况应该是先按照Socket5代理协议把要连接的请求发到代理服务器上才行啊,可是我一点也不懂Socket5代理协议或是HTTP代理协议,哪位高手能不能帮个忙啊!发贴这么长时间了!Top

8 楼kugou123(酷狗)(彪悍的人生,不需要解释 www.xiaozhou.net)回复于 2005-02-26 20:39:28 得分 10

http://www.xiaozhou.net/ReadNews.asp?NewsID=881Top

9 楼yang79tao()回复于 2005-02-27 19:04:42 得分 0

dingTop

10 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-02-28 09:18:24 得分 0

基本可以确定是你代理的部分出问题了,我这儿收集了些资料,希望对你有帮助。  
  http://archive.socks.permeo.com/protocol/socks4.protocol  
  http://www.cnpaf.net/rfc/rfc1928.txt  
  如果协议发生冲突,以rfc1928为准。  
   
  另外,你可以使用一些软件在你自己的机器上架设代理服务器。Top

11 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-02-28 09:19:22 得分 40

(转载,出处忘了)  
  穿透代理服务器编程  
  在网络程序设计过程中,我们经常要与各种类型的代理服务器打交道,比如在企业内部网通过代理去访问Internet网上的服务器等等,一般代理服务器支持几种常见的代理协议标准,如Socks4,Socks5,Http代理,其中Socks5需要用户验证,代理相对复杂。我在查阅RFC文档和相关资料后,特总结一些TCP协议穿透代理服务器的程序片断,希望对大家有所帮助。    
  正文    
  在网络程序设计过程中,我们经常要与各种类型的代理服务器打交道,比如在企业内部网通过代理去访问Internet网上的服务器等等,一般代理服务器支持几种常见的代理协议标准,如Socks4,Socks5,Http代理,其中Socks5需要用户验证,代理相对复杂。我在查阅RFC文档和相关资料后,特总结一些TCP协议穿透代理服务器的程序片断,希望对大家有所帮助。    
   
  //使用到的结构    
  struct   sock4req1    
  {    
  char   VN;    
  char   CD;    
  unsigned   short   Port;    
  unsigned   long   IPAddr;    
  char   other[1];    
  };    
   
  struct   sock4ans1    
  {    
  char   VN;    
  char   CD;    
  };    
   
  struct   sock5req1    
  {    
  char   Ver;    
  char   nMethods;    
  char   Methods[255];    
  };    
   
  struct   sock5ans1    
  {    
  char   Ver;    
  char   Method;    
  };    
   
  struct   sock5req2    
  {    
  char   Ver;    
  char   Cmd;    
  char   Rsv;    
  char   Atyp;    
  char   other[1];    
  };    
   
  struct   sock5ans2    
  {    
  char   Ver;    
  char   Rep;    
  char   Rsv;    
  char   Atyp;    
  char   other[1];    
  };    
   
  struct   authreq    
  {    
  char   Ver;    
  char   Ulen;    
  char   Name[255];    
  char   PLen;    
  char   Pass[255];    
  };    
   
  struct   authans    
  {    
  char   Ver;    
  char   Status;    
  };    
   
  //通过Socks4方式代理    
  if(   !ClientSock.Connect(   g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort)   )    
  {    
  m_sError   =   _T("不能连接到代理服务器!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  char   buff[100];    
  memset(buff,0,100);    
  struct   sock4req1   *m_proxyreq;    
  m_proxyreq   =   (struct   sock4req1   *)buff;    
  m_proxyreq->VN   =   4;    
  m_proxyreq->CD   =   1;    
  m_proxyreq->Port   =   ntohs(GetPort());    
  m_proxyreq->IPAddr   =   inet_addr(GetServerHostName());    
  ClientSock.Send(buff,9);    
  struct   sock4ans1   *m_proxyans;    
  m_proxyans   =   (struct   sock4ans1   *)buff;    
  memset(buff,0,100);    
  ClientSock.Receive(buff,100);    
  if(m_proxyans->VN   !=   0   ||   m_proxyans->CD   !=   90)    
  {    
  m_sError   =   _T("通过代理连接主站不成功!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
   
   
   
   
  //通过Socks5方式代理    
  if(   !ClientSock.Connect(   g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort)   )    
  {    
  m_sError   =   _T("不能连接到代理服务器!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  char   buff[600];    
  struct   sock5req1   *m_proxyreq1;    
  m_proxyreq1   =   (struct   sock5req1   *)buff;    
  m_proxyreq1->Ver   =   5;    
  m_proxyreq1->nMethods   =   2;    
  m_proxyreq1->Methods[0]   =   0;    
  m_proxyreq1->Methods[1]   =   2;    
  ClientSock.Send(buff,4);    
  struct   sock5ans1   *m_proxyans1;    
  m_proxyans1   =   (struct   sock5ans1   *)buff;    
  memset(buff,0,600);    
  ClientSock.Receive(buff,600);    
  if(m_proxyans1->Ver   !=   5   ||   (m_proxyans1->Method!=0   &&   m_proxyans1->Method!=2))    
  {    
  m_sError   =   _T("通过代理连接主站不成功!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  if(m_proxyans1->Method   ==   2)    
  {    
  int   nUserLen   =   strlen(g_ProxyInfo.m_strProxyUser);    
  int   nPassLen   =   strlen(g_ProxyInfo.m_strProxyPass);    
  struct   authreq   *m_authreq;    
  m_authreq   =   (struct   authreq   *)buff;    
  m_authreq->Ver   =   1;    
  m_authreq->Ulen   =   nUserLen;    
  strcpy(m_authreq->Name,g_ProxyInfo.m_strProxyUser);    
  m_authreq->PLen   =   nPassLen;    
  strcpy(m_authreq->Pass,g_ProxyInfo.m_strProxyPass);    
  ClientSock.Send(buff,513);    
  struct   authans   *m_authans;    
  m_authans   =   (struct   authans   *)buff;    
  memset(buff,0,600);    
  ClientSock.Receive(buff,600);    
  if(m_authans->Ver   !=   1   ||   m_authans->Status   !=   0)    
  {    
  m_sError   =   _T("代理服务器用户验证不成功!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  }    
  struct   sock5req2   *m_proxyreq2;    
  m_proxyreq2   =   (struct   sock5req2   *)buff;    
  m_proxyreq2->Ver   =   5;    
  m_proxyreq2->Cmd   =   1;    
  m_proxyreq2->Rsv   =   0;    
  m_proxyreq2->Atyp   =   1;    
  unsigned   long   tmpLong   =   inet_addr(GetServerHostName());    
  unsigned   short   port   =   ntohs(GetPort());    
  memcpy(m_proxyreq2->other,&tmpLong,4);    
  memcpy(m_proxyreq2->other+4,&port,2);    
  ClientSock.Send(buff,sizeof(struct   sock5req2)+5);    
  struct   sock5ans2   *m_proxyans2;    
  memset(buff,0,600);    
  m_proxyans2   =   (struct   sock5ans2   *)buff;    
  ClientSock.Receive(buff,600);    
  if(m_proxyans2->Ver   !=   5   ||   m_proxyans2->Rep   !=   0)    
  {    
  m_sError   =   _T("通过代理连接主站不成功!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
   
   
   
   
  //通过HTTP方式代理    
  if(   !ClientSock.Connect(   g_ProxyInfo.m_strProxyIP,g_ProxyInfo.m_nProxyPort)   )    
  {    
  m_sError   =   _T("不能连接到代理服务器!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  char   buff[600];    
  sprintf(   buff,   "%s%s:%d%s","CONNECT   ",GetServerHostName(),GetPort(),"   HTTP/1.1   User-Agent:   MyApp/0.1   ");    
  ClientSock.Send(buff,strlen(buff));   //发送请求    
  memset(buff,0,600);    
  ClientSock.Receive(buff,600);    
  if(strstr(buff,   "HTTP/1.0   200   Connection   established")   ==   NULL)   //连接不成功    
  {    
  m_sError   =   _T("通过代理连接主站不成功!");    
  ClientSock.Close();    
  return   FALSE;    
  }    
  我们一般先与代理服务器连通,然后向代理服务器发送代理验证的用户名和密码(如果需要,如Socks5代理),验证成功后,再向代理服务器发送需要连接的目的地址和端口。以上代码仅用于TCP连接,如果在内部网侦听或通过UDP协议发送信息,可查阅RFC1829等文档资料。  
  Top

12 楼fisker0303(天塌了,地陷了,小花狗不见了.)回复于 2005-02-28 09:19:41 得分 0

(转载,出处忘了)  
  用socks5进行udp发送数据的过程:    
  你的目的是要和服务器做UDP的数据传送。  
  步骤:    
  1,和代理建立tcp联接,(你已经完成)。  
  2,向代理发送版本的请求信息,   我的实现:  
  void   CCommunicator::SendVer()  
  {  
  int   datasize   =   6;  
  char   tempbuf[6];  
  tempbuf[0]=5;  
  tempbuf[1]=4;//标示后面所根的字接数  
  tempbuf[2]=0;  
  tempbuf[3]=1;  
  tempbuf[4]=2;  
  tempbuf[5]=3;  
  int   senddatalen;    
  senddatalen=send(m_sock,(char*)tempbuf,6,0);  
  }  
  这一步,你已经返回成功,是吗?如果失败,断开建立的tcp联接,如果成功,如果需要用户验证则进行步骤3,否则进行4.  
  3,如果需要用户验证,则类似:    
  BOOL   CCommunicator::SendUserTest()    
  {    
  int   usernamelen=0;    
  int   userpasslen=0;    
  usernamelen=m_strTestUserName.GetLength();    
  userpasslen=m_strTestUserPass.GetLength();    
  char   tempbuf[100];    
  tempbuf[0]=5;    
  tempbuf[1]=usernamelen;//标示后面所根的字接数    
  strcpy(&tempbuf[2],m_strTestUserName);    
  tempbuf[2+usernamelen]=userpasslen;    
  strcpy((char*)&tempbuf   [3+usernamelen],m_strTestUserPass);    
  int   senddatalen;  
  int   len;    
  len=usernamelen+userpasslen+3;    
  senddatalen=send(m_sock,(char*)tempbuf,len,0);  
  }   如果失败,断开建立的tcp联接,   如果用户返回成功,步骤4.  
  4,发送请求的协议类似:    
  void   CCommunicator::SendRequestUDP()    
  {    
  int   const   datasize=10;    
  BYTE   tempbuf[datasize];   tempbuf[0]=5;    
  tempbuf[1]=3;//标示UDP连接    
  tempbuf[2]=0;    
  tempbuf[3]=1;    
  tempbuf[4]=0;    
  tempbuf[5]=0;    
  tempbuf[6]=0;    
  tempbuf[7]=0;    
  *((SHORT*)(&(tempbuf[8])))=m_uBindUDPPort;   //UDP在客户端绑定的端口,就是你本地机器的做udp数据传送的端口调用    
                                                                                        //socket函数后,再调用bind()来邦定一个端口。    
  char   temp;    
  temp=tempbuf[8];    
  tempbuf[8]=tempbuf[9];    
  tempbuf[9]=temp;    
  int   senddatalen=send(m_sock,(char*)tempbuf,datasize,0);    
  }  
  如果失败,断开建立的tcp联接,如果返回成功,验证完毕!步骤5    
  5,真正的数据传送,用代理传送的时候,数据包的前面加上10个字节类似:    
  void   CCommunicator::CopyDataHead(BYTE   *   ptempbuf)    
  {    
  struct   in_addr   addr;    
  addr.s_addr=inet_addr(“202.220.33.333”);//这个ip是服务器端的ip    
  ptempbuf[0]=0;    
  ptempbuf[1]=0;    
  ptempbuf[2]=0;    
  ptempbuf[3]=1;    
  ptempbuf[4]=(char)addr.S_un.S_un_b.s_b1;  
  ptempbuf[5]=(char)addr.S_un.S_un_b.s_b2;    
  ptempbuf[6]=(char)addr.S_un.S_un_b.s_b3;  
  ptempbuf[7]=(char)addr.S_un.S_un_b.s_b4;    
  *((SHORT*)(&(ptempbuf[8])))=m_uServerUDPPort;//服务器的端口,就是你最终要发到那个服务器的端口,也就是你的qq服务器。    
  char   temp;    
  temp=ptempbuf[8];    
  ptempbuf[8]=ptempbuf[9];    
  ptempbuf[9]=temp;    
  }    
  真正发送的时候类似:  
  int   CCommunicator::SendBufferUDP(LPBYTE   lpBuf,int   nLen)    
  {    
  BYTE   tempbuf[1000];    
  int   iHeadData=0;    
  struct   sockaddr_in   her;    
  her.sin_family=AF_INET;    
  her.sin_addr.s_addr=inet_addr(m_szProxyAddr);//代理服务器    
  her.sin_port=htons(m_uSocksPort);//发送请求的时候返回的代理服务器端的端口,记住,这是最重要的。    
  CopyDataHead(tempbuf);    
  iHeadData=10;    
  nLen=nLen+10;    
  int   addr_len;    
  addr_len=sizeof(struct   sockaddr);    
  CopyMemory((char*)&tempbuf[iHeadData],lpBuf,nLen);    
  int   returndatalen=sendto(m_socket,(char   *)tempbuf,nLen,0,(struct   sockaddr   *)&her,addr_len);    
  }Top

13 楼louifox(兰陵笑笑生)回复于 2005-02-28 10:20:20 得分 0

dingTop

14 楼gdy119(夜风微凉)回复于 2005-02-28 13:14:59 得分 0

看一下过代理的文章Top

15 楼T97102003(池塘里的水手)回复于 2005-02-28 13:21:37 得分 0

upTop

相关问题

  • 高分请教一个Socket编程服务器端的问题!
  • 关于服务器编程
  • 关于服务器编程
  • SOCKET编程:在服务器端如何判断客户已断开(如掉电)?
  • 在linux服务器端用C语言进行socket编程一问
  • 江湖救急--------VOD服务器编程(多线程 + SOCKET).大侠请进
  • 如何用socket编程实现通过代理服务器通讯?
  • 用socket编程,如何通过http代理访问远端web服务器
  • 关于win socket编程 客户程序 服务器程序 帮我改一下
  • 用Socket Api编程时,对多个客户的服务器端编程问题!!请大家帮手!!!

关键词

  • .net
  • 服务器
  • 连接
  • 端口
  • 协议
  • 联接
  • tcp
  • 客户
  • 代码
  • 验证

得分解答快速导航

  • 帖主:yang79tao
  • kugou123
  • fisker0303

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo