#include <stdio.h>
#include <winsock2.h> #define MAXBUFLEN 20480 #define HTTPADDLEN 50 #define TIMEWAIT 2000 #pragma comment(lib,"ws2_32.lib") SOCKET Global[]; DWORD WINAPI Proxy( LPVOID pSocket); int ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr); int main(int argc,char * argv[]) { SOCKET MainSocket,ClientSocket; struct sockaddr_in Host,Client; WSADATA WsaData; int AddLen,i; //初始化 if(WSAStartup(MAKEWORD(,),&WsaData) < ) { printf("初始化失败\n"); return ; } //创建socket端口 MainSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(MainSocket == SOCKET_ERROR) { printf("端口创建错误\n"); return ; } Host.sin_family = AF_INET; Host.sin_port = htons(); Host.sin_addr.s_addr = inet_addr("127.0.0.1"); printf("正在工作\n"); //绑定socket if(bind(MainSocket,(SOCKADDR *)&Host,sizeof(Host)) != ) { printf("绑定错误\n"); } i = ; //监听 if(listen(MainSocket,) == SOCKET_ERROR) { printf("监听错误\n"); } AddLen = sizeof(Client); //连接新的客户 i = ; for(;;) { ClientSocket = accept(MainSocket,(SOCKADDR *)&Client,&AddLen); if(ClientSocket == SOCKET_ERROR) { printf("接受客户请求错误!\n"); } printf("."); i ++ ; if( i >= ) i = ; Global[i] = ClientSocket; //对于每一个客户启动不同的线程程进行控制 //这个地方在使用ClientSocket的时候,要不要保证在某一时刻内只能有一个进程使用? CreateThread(NULL,,Proxy,(LPVOID)Global[i],,NULL); } return ; } DWORD WINAPI Proxy( LPVOID pSocket) { SOCKET ClientSocket; char ReceiveBuf[MAXBUFLEN]; int DataLen; struct sockaddr_in ServerAddr; SOCKET ProxySocket; int i = ; int time = TIMEWAIT; //得到参数中的端口号信息 ClientSocket = (SOCKET)pSocket; //接受第一次请求信息 memset(ReceiveBuf,,MAXBUFLEN); DataLen = recv(ClientSocket,ReceiveBuf,MAXBUFLEN,); if(DataLen == SOCKET_ERROR) { printf("错误\n"); closesocket(ClientSocket); return ; } if(DataLen == ) { closesocket(ClientSocket); return ; } //处理请求信息,分离出服务器地址 if( ParseHttpRequest(ReceiveBuf,DataLen,(void *)&ServerAddr) < ) { closesocket(ClientSocket); goto error; } //创建新的socket用来和服务器进行连接 ProxySocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //设置超时时间 setsockopt(ProxySocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&time,sizeof(time)); if(ProxySocket == SOCKET_ERROR) { printf("端口创建错误\n"); return ; } if(connect(ProxySocket,(SOCKADDR *)&ServerAddr,sizeof(ServerAddr)) == SOCKET_ERROR) { //printf("连接服务器错误"); goto error; } //开始进行数据传输处理 //发送到服务器端 if(send(ProxySocket,ReceiveBuf,DataLen,) == SOCKET_ERROR) { //printf("数据发送错误"); goto error; } //从服务器端接受数据 while(DataLen > ) { memset(ReceiveBuf,,MAXBUFLEN); if((DataLen = recv(ProxySocket,ReceiveBuf,MAXBUFLEN,)) <= ) { // printf("数据接受错误"); break; } else //发送到客户端 if(send(ClientSocket,ReceiveBuf,DataLen,) < ) { // printf("数据发送错误"); break; } } error: closesocket(ClientSocket); closesocket(ProxySocket); return ; } int ParseHttpRequest(char * SourceBuf,int DataLen,void * ServerAddr) { char * HttpHead = "http://"; char * FirstLocation = NULL; char * LastLocation = NULL; char * PortLocation = NULL; char ServerName[HTTPADDLEN]; char PortString[]; int NameLen; struct hostent * pHost; struct sockaddr_in * pServer = (struct sockaddr_in *)ServerAddr; //取得http://的位置 FirstLocation = strstr(SourceBuf,HttpHead) + strlen(HttpHead); //取得/的位置 printf("%s\n",FirstLocation); LastLocation=strstr(FirstLocation,"/"); //得到http://和/之间的服务器的名称 memset(ServerName,,HTTPADDLEN); memcpy(ServerName,FirstLocation,LastLocation - FirstLocation); //有些情况下,请求的地址中带有端口号格式为“:+ 端口号”; //取得 :的位置 PortLocation = strstr(ServerName,":"); //填充server结构 pServer->sin_family = AF_INET; //在url中制定了服务器端口 if(PortLocation != NULL) { NameLen = PortLocation - ServerName -; memset(PortString,,); memcpy(PortString,PortLocation + ,NameLen); pServer->sin_port = htons((u_short)atoi(PortString)); *PortLocation = ; } else//在url中,没有制定服务器端口 { pServer->sin_port=htons(); } if(NameLen > HTTPADDLEN) { printf("服务器名字太长\n"); return -; } //得到服务器信息 //如果地址信息是以IP地址(192.168.0.1)的形式出现的 if(ServerName[] >= '' && ServerName[] <= '') { pServer->sin_addr.s_addr = inet_addr(ServerName); } //以域名的形式出现的(www.sina.com.cn) else { pHost = (struct hostent *)gethostbyname(ServerName); if(!pHost) { printf("取得主机信息错误\n"); printf("%s\n",ServerName); return -; } memcpy(&pServer->sin_addr,pHost->h_addr_list[],sizeof(pServer->sin_addr)); } return ; }

最新文章

  1. Linux配置本地无密码访问
  2. Ubuntu GNOME 16.10 Beta 1问世了!
  3. TCP连接的三次握手和四次解散过程
  4. java中&quot;与&quot;和&quot;或&quot;
  5. .NET MVC4 数据验证Model(二)
  6. Linux上F上传文件到FTP服务器
  7. 我的工具箱之FileZilla_3.11.0.1_win32-setup.1432524055
  8. appjs desktop2
  9. Cognos 增加全局类
  10. 月半小夜曲下的畅想--DOCTYPE模式
  11. WPF的ScrollViewer鼠标的滚动
  12. Come and join us at English corner
  13. [C# 网络编程系列]专题七:UDP编程补充——UDP广播程序的实现
  14. POJ Wormholes 3259
  15. 201621123040《Java程序设计》第十周学习总结
  16. C#编程时应注意的性能处理
  17. 解题(Solution -4Sum)
  18. SpringBoot介绍
  19. java.net.URL 模拟用户登录网页并维持session【转】
  20. javascript篇-typeof,instanceof,constructor,toString判断数据类型的用法和区别

热门文章

  1. Linux库的创建和使用
  2. SVN、TortoiseSVN相关问题
  3. 玩转Android Camera开发(四):预览界面四周暗中间亮,仅仅拍摄矩形区域图片(附完整源代码)
  4. 〖Linux〗Clang/Clang++ for Android Binary/NDK build(二进制可执行文件/NDK编译)
  5. SwaggerUI+SpringMVC——构建RestFul API的可视化界面
  6. css中clear属性的认识
  7. java常见错误--Access restriction: The type BASE64Encoder
  8. 用户研究Q&amp;A(1)
  9. jQuery使用正则判断是否含有非法字符
  10. mysql中的慢查询日志