http,协议源码

发布时间:2016-11-27 来源: 协议 点击:

篇一:socks5协议转http协议源码

socks5代理可以看rfc 1928

socks5的用户名口令认证方法看rfc 1929

http代理可以看 rfc2616

socks5代理可以支持tcp和udp 而http只支持tcp

所以这个代理转换器只支持tcp

写作原因

很多软件都有socks5认证方法 但是它们不支持http认证方法

而从原理上可以使用http认证方法(因为它们没有使用udp)

所以写这个软件可以方便的使其它程序可以使用http代理

如联众 或是foxmail

CODE

#include <winsock2.h>

#include <stdio.h>

#include <stdlib.h>

#define

INIT_SOCKET(){WSADATAwsadata;WSAStartup(MAKEWORD(2,2),&wsadata);}

#define CLOSESOCKET(x) closesocket(x)

#define CLEAN_SOCKET() {WSACleanup();}

// http.c 实现http代理功能

#define PROTO_EXCHANGE_TIMEOUT 15

#define PROTO_RECVRESP_TIMEOUT 75

#define PROTO_SENDRESP_TIMEOUT 10

#define WAIT_AND_RECV(sd,buf,len,waittime,recvflags) do{\

struct fd_set sset;\

struct timeval waited;\

waited.tv_sec= waittime;waited.tv_usec= 0;\

FD_ZERO(&sset);FD_SET(sd,&sset);\

if(select(sd+1,&sset,NULL,NULL,&waited) != 1 || (len = recv(sd,buf,len,recvflags)) == -1 )\

len = -1;\

}while(0);

#define DEBUG_DUMPprintf

static int httpproxy_connect(const char*proxyaddr,int proxyport,

const char*dstaddr,int dstport)

{

int proxysd = -1;

char buf[2048];

int len;

char *ptoken;

int status;

struct sockaddr_in inaddr;

if( !proxyaddr || !proxyaddr[0] || proxyport < 1

||!dstaddr || !dstaddr[0] )

return -1;

DEBUG_DUMP("代理:%s:%d,目标:%s:%d\n",proxyaddr,proxyport,dstaddr,dstport);

len = sizeof(inaddr);

memset(&inaddr,0,len);

if( (inaddr.sin_addr.s_addr = inet_addr(proxyaddr) ) == INADDR_NONE ) return -1;

inaddr.sin_family = AF_INET;

inaddr.sin_port= htons(proxyport);

// connect to proxy

if((proxysd = socket(AF_INET,SOCK_STREAM,0)) == -1 )

return -1;

if( connect(proxysd,(struct sockaddr*)&inaddr,len))

goto errorparse;

// 发送connect请求并判断返回,根据HTTP协议说明,详细内容请看RFC2616 // HTTP代理使用CONNECT指令实现,CONNECT时指定选端的地址与端口号,

// 当代理服务器返回成功后(状态值是2xx),后面的代理服务器不再对此连接的数据

// 进行HTTP协议处理

if( dstport > 0 )

len = sprintf(buf,"CONNECT %s:%d HTTP/1.1\r\n\r\n",dstaddr,dstport); else

len = sprintf(buf,"CONNECT %s HTTP/1.1\r\n\r\n",dstaddr);

if( send(proxysd,buf,len,0) != len ){

DEBUG_DUMP("发送CONNECT请求失败:包内容:%s\n",buf);

goto errorparse;

}

len = sizeof(buf)-1;

WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,MSG_PEEK);

if( len == -1){

DEBUG_DUMP("接收CONNECT响应失败\n");

goto errorparse;

}

buf[len] = 0;

DEBUG_DUMP("CONNECT响应为:%s|\n",buf);

if( strnicmp(buf,"HTTP/1.",7)

|| (!strstr(buf,"\r\n\r\n") && !strstr(buf,"\n\n")))

goto errorparse;

ptoken = buf;

while(!isspace(*ptoken) && *ptoken) ptoken ++;

status = atoi(ptoken);

if( status < 300 && status > 199 ){

ptoken = strstr(buf,"\r\n\r\n");

if( ptoken )

len = ptoken - buf +4;

else{

ptoken = strstr(buf,"\n\n");

len = ptoken - buf +2;

}

WAIT_AND_RECV(proxysd,buf,len,PROTO_RECVRESP_TIMEOUT,0); return proxysd;

}

errorparse:

CLOSESOCKET(proxysd);

return -1;

}

// sd [in] 使用socks5的客户端的连接id

// proxyaddr[in] http代理地址

// proxyport[in] http代理端口

// return:

// -1 失败

// >=0 与http代理的连接id

static int socks5_accept(int sd,const char *proxyaddr,int proxyport)

{

unsigned char buf[512];

int len = 2;

int i= 0;

char dstaddr[260];

int dstport;

if( !proxyaddr || !proxyaddr[0] || proxyport <1 )

return -1;

// 处理协商,现在只处理无认证情况,无论对方会不会处理这种情况 // 没有要求无认证方式,sorry,那我就不理它

// 另外只处理SOCKS5的CONNECT命令,其它不处理

WAIT_AND_RECV(sd,(char*)buf,len,PROTO_EXCHANGE_TIMEOUT,0); if( len != 2 || buf[0] != 5 ){

DEBUG_DUMP("接收socks5协商包失败,len:%d,buf[0]:%d\n",len,buf[0]); return -1;

}

len = buf[1];

i= len;

WAIT_AND_RECV(sd,(char*)buf,i,PROTO_EXCHANGE_TIMEOUT,0); if( len != i ){

DEBUG_DUMP("接收socks5协商包失败,想接收%d,收到:%d\n",len,i); return -1;

}

for( i = 0;i< len && buf[i];i++ );

if( i == len ){

DEBUG_DUMP("用户没有请求socks5无认证方法:\n");

return -1;

}

buf[0] = 5;

buf[1] = 0;

if( send(sd,(char*)buf,2,0) != 2)

return -1;

len = 5;

WAIT_AND_RECV(sd,(char*)buf,len,PROTO_RECVRESP_TIMEOUT,0); if( len != 5 || buf[0] != 5 || buf[1] != 1 ){

DEBUG_DUMP("处理socks5CONNECT命令失败:len:%d,buf[0]:0x%x,buf[1]:0x%x\n",len,buf[0],buf[1]);

return -1;

}

switch( buf[3] ){

case 1: // 是IP地址

len = 5;

WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0);

if( len != 5 ){

DEBUG_DUMP("处理socks5CONNECT命令[IP方式]失败:len:%d\n",len);

return -1;

}

{

struct in_addr addr;

memcpy((char*)&addr.s_addr,buf+4,4);

strcpy(dstaddr,inet_ntoa(addr));

dstport = ntohs(*(unsigned short*)(buf+8));

}

break;

case 3: // 是域方式

len = buf[4]+2;

WAIT_AND_RECV(sd,(char*)buf+5,len,PROTO_RECVRESP_TIMEOUT,0);

if( len != buf[4]+2 ){

DEBUG_DUMP("处理socks5CONNECT命令[域方式]失败:len:%d\n",len);

return -1;

}

memcpy(dstaddr,buf+5,buf[4]);

dstaddr[buf[4]] = 0;

dstport = ntohs(*(unsigned short*)(buf+5+buf[4]));

break;

default:

DEBUG_DUMP("处理socks5CONNECT命令[]失败:未知方式:type:0x%x\n",buf[3]);

return -1;

}

return httpproxy_connect(proxyaddr,proxyport,dstaddr,dstport);

}

int listenport(int port,const char*addr)

{

int len = sizeof(struct sockaddr_in);

struct sockaddr_in bindaddr;

int sd = socket(AF_INET,SOCK_STREAM,0);

if( sd == -1)

return -1;

memset(&bindaddr,0,len);

bindaddr.sin_family = AF_INET;

bindaddr.sin_port= htons(port);

if( addr && addr[0] )

bindaddr.sin_addr.s_addr = inet_addr(addr);

if( bind ( sd,(struct sockaddr*)&bindaddr,&len) || listen(sd,100 )){

DEBUG_DUMP("打开端口失败,port:%d\n",port);

CLOSESOCKET(sd);

return -1;

}

return sd;

}

void running(int sd){

int ad;

if( sd == -1 )

return;

while(1){

int proxyid;

char buf[10240];

int len;

int maxid;

int actcount;

ad = accept(sd,NULL,NULL);

if( ad == -1 )

break;

篇二:C编程实现http协议

C编程实现http协议

发布日期:2009-03-13来源:互联网作者:佚名

大家都很熟悉HTTP协议的应用,因为每天都在网络上浏览着不少东西,也都知道是HTTP协议是相当简单的。每次用到FlashGet之类的下载软件下载网页,当用到那个“用FlashGet下载全部链接”时总觉得很神奇。

后来想想,其实要实现这些下载功能也并不难,只要按照HTTP协议发送request,然后对接收到的数据进行分析,如果页面上还有href之类的链接指向标志就可以进行深一层的下载了。HTTP协议目前用的最多的是1.1版本,要全面透彻地搞懂它就参考RFC2616文档吧。 下面是我用C语言编程写的一个http下载程序,希望对大家有些启发。源代码如下:

/******* http客户端程序 httpclient.c ************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <errno.h>

#include <unistd.h>

#include <netinet/in.h>

#include <limits.h>

#include <netdb.h>

#include <arpa/inet.h>

#include <ctype.h>

//////////////////////////////httpclient.c 开始///////////////////////////////////////////

/********************************************

功能:搜索字符串右边起的第一个匹配字符

********************************************/

char * Rstrchr(char * s, char x) {

int i = strlen(s);

if(!(*s)) return 0;

while(s[i-1]) if(strchr(s + (i - 1), x)) return (s + (i - 1)); else i--;

return 0;

}

/********************************************

功能:把字符串转换为全小写

********************************************/

void ToLowerCase(char * s) {

while(*s) *s=tolower(*s++);

}

/**************************************************************

功能:从字符串src中分析出网站地址和端口,并得到用户要下载的文件

***************************************************************/

void GetHost(char * src, char * web, char * file, int * port) {

char * pA;

char * pB;

memset(web, 0, sizeof(web));

memset(file, 0, sizeof(file));

*port = 0;

if(!(*src)) return;

pA = src;

if(!strncmp(pA, "http://", strlen("http://"))) pA = src+strlen("http://");

else if(!strncmp(pA, "https://", strlen("https://"))) pA = src+strlen("https://");

pB = strchr(pA, '/');

if(pB) {

memcpy(web, pA, strlen(pA) - strlen(pB));

if(pB+1) {

memcpy(file, pB + 1, strlen(pB) - 1);

file[strlen(pB) - 1] = 0;

}

}

else memcpy(web, pA, strlen(pA));

if(pB) web[strlen(pA) - strlen(pB)] = 0;

else web[strlen(pA)] = 0;

pA = strchr(web, ':');

if(pA) *port = atoi(pA + 1);

else *port = 80;

}

/*********************************************************************

*filename: httpclient.c

*purpose: HTTP协议客户端程序,可以用来下载网页

*wrote by: zhoulifa(zhoulifa@163.com) 周立发

* Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言

*date time:2006-03-11 21:49:00

*Note: 任何人可以任意复制代码并运用这些代码,当然包括你的商业用途

* 但请遵循GPL

*********************************************************************/

int main(int argc, char *argv[])

{

int sockfd;

char buffer[1024];

struct sockaddr_in server_addr;

struct hostent *host;

int portnumber,nbytes;

char host_addr[256];

char host_file[1024];

char local_file[256];

FILE * fp;

char request[1024];

int send, totalsend;

int i;

char * pt;

if(argc!=2)

{

fprintf(stderr,"Usage:%s web-address\a\n",argv[0]);

exit(1);

}

printf("parameter.1 is: %s\n", argv[1]);

ToLowerCase(argv[1]);/*将参数转换为全小写*/

printf("lowercase parameter.1 is: %s\n", argv[1]);

GetHost(argv[1], host_addr, host_file, &portnumber);/*分析网址、端口、文件名等*/printf("webhost:%s\n", host_addr);

printf("hostfile:%s\n", host_file);

printf("portnumber:%d\n\n", portnumber);

if((host=gethostbyname(host_addr))==NULL)/*取得主机IP地址*/

{

fprintf(stderr,"Gethostname error, %s\n", strerror(errno));

exit(1);

}

/* 客户程序开始建立 sockfd描述符 */

if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)/*建立SOCKET连接*/

{

fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));

exit(1);

}

/* 客户程序填充服务端的资料 */

bzero(&server_addr,sizeof(server_addr));

server_addr.sin_family=AF_INET;

server_addr.sin_port=htons(portnumber);

server_addr.sin_addr=*((struct in_addr *)host->h_addr);

/* 客户程序发起连接请求 */

if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)/*连接网站*/{

fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));

exit(1);

}

sprintf(request, "GET /%s HTTP/1.1\r\nAccept: */*\r\nAccept-Language: zh-cn\r\n\

User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)\r\n\

Host: %s:%d\r\nConnection: Close\r\n\r\n", host_file, host_addr, portnumber);

printf("%s", request);/*准备request,将要发送给主机*/

/*取得真实的文件名*/

if(host_file && *host_file) pt = Rstrchr(host_file, '/');

else pt = 0;

memset(local_file, 0, sizeof(local_file));

if(pt && *pt) {

if((pt + 1) && *(pt+1)) strcpy(local_file, pt + 1);

else memcpy(local_file, host_file, strlen(host_file) - 1);

}

else if(host_file && *host_file) strcpy(local_file, host_file);

else strcpy(local_file, "index.html");

printf("local filename to write:%s\n\n", local_file);

/*发送http请求request*/

send = 0;totalsend = 0;

nbytes=strlen(request);

while(totalsend < nbytes) {

send = write(sockfd, request + totalsend, nbytes - totalsend);

if(send==-1) {printf("send error!%s\n", strerror(errno));exit(0);}

totalsend+=send;

printf("%d bytes send OK!\n", totalsend);

}

fp = fopen(local_file, "a");

if(!fp) {

printf("create file error! %s\n", strerror(errno));

return 0;

}

printf("\nThe following is the response header:\n");

i=0;

/* 连接成功了,接收http响应,response */

while((nbytes=read(sockfd,buffer,1))==1)

{

if(i < 4) {

if(buffer[0] == '\r' || buffer[0] == '\n') i++;

else i = 0;

printf("%c", buffer[0]);/*把http头信息打印在屏幕上*/ }

else {

fwrite(buffer, 1, 1, fp);/*将http主体信息写入文件*/ i++;

if(i%1024 == 0) fflush(fp);/*每1K时存盘一次*/ }

}

fclose(fp);

/* 结束通讯 */

close(sockfd);

exit(0);

}

篇三:http协议

HTTP 学习资料 Http客户端程序已集成在Java语言中,可以通过URLConnection类调用。遗憾的 是,由于SUN没有公布Http客户程序的源码,它实现的细节仍是一个谜。本文根据HTTP

协议规范,用Java.net.Socket类实现一个HTTP协议客户端程序。

1.Socket类:

了解TCP/IP协议集通信的读者知道,协议间的通信是通过Socket完成的。在 Java.net包中,Socket类就是对Socket的具体实现。它通过连接到主机后,返回一个

I/O流,实现协议间的信息交换。

2.HTTP协议

HTTP协议同其它TCP/IP协议集中的协议一样,是遵循客户/服务器模型工作的。客 户端发往服务端的信息格式如下:

------------------------------

请求方法URLHTTP协议的版本号

提交的元信息

**空行**

实体

------------------------------

请求方法是对这次连接工作的说明,目前HTTP协议已经发展到1.1版,它包括GET、 HEAD、POST、DELETE、OPTIONS、TRACE、PUT七种。元信息是关于当前请求的信息。通

过分析元信息,可以检查实体数据是否完整,接收过程是否出错,类型是否匹配等。元 信息的引入使HTTP协议通信更加稳妥可靠。实体是请求的具体内容。 将上述报文发往Web服务器,如果成功,应答格式如下:

--------------------------------

HTTP协议的版本号应答状态码应答状态码说明

接收的元信息

**空行**

实体

--------------------------------

以上报文发向客户端,并且接收成功,彼此间关闭连接,完成一次握手。 下面用最常用的GET方法,来说明具体的报文应用

----------------------------------

GETHTTP/1.0

accept:www/source;text/html;image/gif;image/jpeg;*/*

User_Agent:myAgent

**空行**

-----------------------------------

这个报文是向主机请求一个缺省HTML文档。客户端HTTP协议版本

1

号是1.0版,元信息包括可接收的文件格式,用户代理,每一段之间用回车换行符分 隔,最后以一个空行结束。发向服务器后,如果执行过程正常,服务器返回以下代码: ------------------------------------

HTTP/1.1200OK

Date:Tue,14Sep199902:19:57GMT

Server:Apache/1.2.6

Connection:close Content-Type:text/html

**空行**

<html><head>...</head><body>...</body></html>

------------------------------------

HTTP/1.1表示这个HTTP服务器是1.1版,200是服务器对客户请求的应答状态码,OK

是对应答状态码的解释,之后是这个文档的元信息和文档正文。(相关应答状态码和元 信息的解释请参阅Inetrnet标准草案:RFC2616)。

Http.java

importjava.net.*;

importjava.io.*;

importjava.util.Properties; importjava.util.Enumeration;

publicclassHttp{

protectedSocketclient;

protectedBufferedOutputStreamsender;

protectedBufferedInputStreamreceiver;

protectedByteArrayInputStreambyteStream;

protectedURLtarget;

privateintresponseCode=-1;

privateStringresponseMessage="";

privateStringserverVersion="";

privatePropertiesheader=newProperties();

publicHttp(){}

publicHttp(Stringurl){

GET(url);

}

/*GET方法根据URL,会请求文件、数据库查询结果、程序运行结果等多种内容*/ publicvoidGET(Stringurl){

try{

checkHTTP(url);

openServer(target.getHost(),target.getPort());

2

Stringcmd="GET"+getURLFormat(target)+"HTTP/1.0\r\n"

+getBaseHeads()+"\r\n";

sendMessage(cmd);

receiveMessage();

}catch(ProtocolExceptionp){

p.printStackTrace();

return;

}catch(UnknownHostExceptione){

e.printStackTrace();

http 协议源码

return;

}catch(IOExceptioni){

i.printStackTrace();

return;

}

}

/*

*HEAD方法只请求URL的元信息,不包括URL本身。若怀疑本机和服务器上的 *文件相同,用这个方法检查最快捷有效。

*/

publicvoidHEAD(Stringurl){

try{

checkHTTP(url);

openServer(target.getHost(),target.getPort());

Stringcmd="HEAD"+getURLFormat(target)+"HTTP/1.0\r\n"

+getBaseHeads()+"\r\n";

sendMessage(cmd);

receiveMessage();

}catch(ProtocolExceptionp){

p.printStackTrace();

return;

}catch(UnknownHostExceptione){

e.printStackTrace();

return;

}catch(IOExceptioni){

i.printStackTrace();

return;

}

}

/*

*POST方法是向服务器传送数据,以便服务器做出相应的处理。例如网页上常用的 *提交表格。

3

publicvoidPOST(Stringurl,Stringcontent){

try{

checkHTTP(url);

openServer(target.getHost(),target.getPort());

Stringcmd="POST"+getURLFormat(target)+"HTTP/1.0\r\n"+getBaseHeads();

cmd+="Content-type:application/x-www-form-urlencoded\r\n";

cmd+="Content-length:"+content.length()+"\r\n\r\n";

cmd+=content+"\r\n";

sendMessage(cmd);

receiveMessage();

}catch(ProtocolExceptionp){

p.printStackTrace(); return;

}catch(UnknownHostExceptione){

e.printStackTrace();

return;

}catch(IOExceptioni){

i.printStackTrace();

return;

}

}

protectedvoidcheckHTTP(Stringurl)throwsProtocolException{

try{

URLtarget=newURL(url);

if(target==null||!target.getProtocol().toUpperCase().equals("HTTP")) thrownewProtocolException("这不是HTTP协议");

this.target=target;

}catch(MalformedURLExceptionm){

thrownewProtocolException("协议格式错误");

}

}

/*

*与Web服务器连接。若找不到Web服务器,InetAddress会引发UnknownHostException

*异常。若Socket连接失败,会引发IOException异常。

*/

protectedvoidopenServer(Stringhost,intport)throws

UnknownHostException,IOException{

header.clear();

responseMessage="";responseCode=-1;

4

if(client!=null)closeServer();

if(byteStream!=null){

byteStream.close();byteStream=null;

}

InetAddressaddress=InetAddress.getByName(host);

client=newSocket(address,port==-1?80:port);

sender=newBufferedOutputStream(client.getOutputStream()); receiver=newBufferedInputStream(client.getInputStream()); }catch(UnknownHostExceptionu){

throwu;

}catch(IOExceptioni){

throwi;

} }

/*关闭与Web服务器的连接*/

protectedvoidcloseServer()throwsIOException{

if(client==null)return; try{

client.close();sender.close();receiver.close();

}catch(IOExceptioni){

throwi;

}

client=null;sender=null;receiver=null;

}

protectedStringgetURLFormat(URLtarget){

Stringspec="http://"+target.getHost();

if(target.getPort()!=-1)

spec+=":"+target.getPort();

returnspec+=target.getFile();

}

/*向Web服务器传送数据*/

protectedvoidsendMessage(Stringdata)throwsIOException{ sender.write(data.getBytes(),0,data.length());

sender.flush();

}

/*接收来自Web服务器的数据*/

protectedvoidreceiveMessage()throwsIOException{

bytedata[]=newbyte[1024];

intcount=0;

5

相关热词搜索:源码 协议 http 安卓qq2016协议源码 qq安卓协议机器人源码 yy协议pc版源码

热点文章阅读

版权所有 小龙文挡网 www.xltkwj.com