#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 ; }

黑客编程教程(十五)HTTP代理的更多相关文章

  1. webpack4 系列教程(十五):开发模式与webpack-dev-server

    作者按:因为教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十五):开发模式与 webpack-dev-server>原文地址.更欢迎来我的 ...

  2. 无废话ExtJs 入门教程十五[员工信息表Demo:AddUser]

    无废话ExtJs 入门教程十五[员工信息表Demo:AddUser] extjs技术交流,欢迎加群(201926085) 前面我们共介绍过10种表单组件,这些组件是我们在开发过程中最经常用到的,所以一 ...

  3. RabbitMQ入门教程(十五):普通集群和镜像集群

    原文:RabbitMQ入门教程(十五):普通集群和镜像集群 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.c ...

  4. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  5. 并发编程(十五)——定时器 ScheduledThreadPoolExecutor 实现原理与源码深度解析

    在上一篇线程池的文章<并发编程(十一)—— Java 线程池 实现原理与源码深度解析(一)>中从ThreadPoolExecutor源码分析了其运行机制.限于篇幅,留下了Scheduled ...

  6. Unity3D脚本中文系列教程(十五)

    http://dong2008hong.blog.163.com/blog/static/4696882720140322449780/ Unity3D脚本中文系列教程(十四) ◆ LightRend ...

  7. 黑客编程教程(二)Win API编程简介

    第二节 Win API编程简介 下面介绍一下WIN API. 我们需要自己编写一个工具时,必然会用到很多操作windows和控制windows的函数,这些函数就是windows API. API是Ap ...

  8. 黑客编程教程(十四)单线程TCP端口扫描器

    #include<winsock2.h> #include<stdio.h> #include <time.h> //计时需要用到的头文件 #pragma comm ...

  9. Java编程思想(十五) —— 类型信息之反射

    讲完.class,Class之后,继续. 1)泛化的Class引用 Class也能够增加泛型,增加之后会进行类型检查. 贴一下书上原话,Class<?>优于Class,尽管他们是等价的,C ...

随机推荐

  1. [置顶] Zend Optimizer 和 Zend Debugger 同时安装

    下载地址: Zend Optimizer:  http://download.csdn.net/detail/wf120355/6479947 Zend Debugger: http://downlo ...

  2. 页面可视化编辑ckeditor(web基础学习笔记十五)

    一.CKedit下载ckedit 下载地址:http://ckeditor.com/ 二.ckedit的引入 2.1.解压并将ckedit复制到项目中 2.2.在页面中引入 在页面头部加入 <s ...

  3. 移动H5前端性能优化指南[转]

    移动H5前端性能优化指南 米随随2015.01.23 移动H5前端性能优化指南 概述 1. PC优化手段在Mobile侧同样适用2. 在Mobile侧我们提出三秒种渲染完成首屏指标3. 基于第二点,首 ...

  4. Asp.Net MVC:return View()、return View("Login")、return Login()、return RedirectToAction("Login") 的区别

    在做登录页面的时候发现的一些情况: ------------------------------------------------------------------------- public A ...

  5. 算法笔记_170:历届试题 分糖果(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 有n个小朋友围坐成一圈.老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏: 每个小朋友都把自己的糖果分一半给左手边的孩子. 一轮分糖后 ...

  6. css before和after伪元素应用

    1.说明 ":before" 伪元素可以在元素的内容前面插入新内容. ":after" 伪元素可以在元素的内容之后插入新内容. 伪元素默认展示为inline, ...

  7. 6、javac命令详解

    javac [ options ] [ sourcefiles ] [ @files ] 参数可按任意次序排列. options 命令行选项. sourcefiles 一个或多个要编译的源文件(例如 ...

  8. 商家 APP 如何接入新版支付宝支付,老版本商家如何升级

    代码地址如下:http://www.demodashi.com/demo/14006.html 前言 支付宝移动支付2.0版本对比1.0版本做了较大更新,新申请的商家都需要采用最新2.0版本 SDK ...

  9. 警告: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:

    当你用Eclipse运行web项目的时候,你就会看到控制台出现: 警告: [SetContextPropertiesRule]{Context} Setting property 'source' t ...

  10. PHP-数据库永久连接

    以下为PHP官网上对数据库永久连接做的解释: 永久的数据库连接是指在脚本结束运行时不关闭的连接.当收到一个永久连接的请求时.PHP 将检查是否已经存在一个(前面已经开启的)相同的永久连接.如果存在,将 ...