您的位置:首页 > 理论基础 > 计算机网络

linux下纯C简单的HTTP POST请求 客户端模型

2015-12-30 00:19 561 查看
其实无非要实现有两点,

TCP客户端的模型

HTTP POST协议

先来看看我的TCP模型的实现

#ifndef _TUOBAO_TCP_CLIENT_

#define _TUOBAO_TCP_CLIENT_

#include <netinet/in.h>

#include <sys/socket.h>

typedef struct _tuobao_tcpclient{

int socket;

int remote_port;

char remote_ip[16];

struct sockaddr_in _addr;

int connected;

} tuobao_tcpclient;

int tuobao_tcpclient_create(tuobao_tcpclient *,const char *host, int port);

int tuobao_tcpclient_conn(tuobao_tcpclient *);

int tuobao_tcpclient_recv(tuobao_tcpclient *,char **lpbuff,int size);

int tuobao_tcpclient_send(tuobao_tcpclient *,char *buff,int size);

int tuobao_tcpclient_close(tuobao_tcpclient *);

#endif

上面的代码应该也不用说太多,光看这个这些函数的命名也差不多知道嘛意思了

定义一个结构体,有远程IP及端口,连接状态(注:连接状态是为了保持长连接用的,但事实上post请求的时候,根本就没有保持,所以,基本上没用)

然后是五个tcp函数

tuobao_tcpclient_create:根据服务器IP或者域名,以及端口填充tcpclient结构,主要是申请个socket及填一下sockaddr_in

tuobao_tcpclient_conn:连接到远程端口,并修改tcpclient的连接状态

tuobao_tcpclient_recv:接收远程指定字节数的数据,并分配空间到lpBuf,如果size为0,就阻塞直到连接关闭

tuobao_tcpclient_send:发送buf,size为buf长度

tuobao_tcpclient_close:关闭socket并且设置连接状态

好了,直接贴代码算了

tuobao_tcpclient.c

现在来看看http协议的头吧

虽然搞好几年的asp.net,但是因为微软为我们封装得太好了,一直没有关注http协议的post头应该是怎么样?

想想,其实很简单,看看人家IE是怎么发出去的就知道了

ubuntu下,先用nc工作监听一下,win下面随便发个请求

html

看nc的响应

linbc@cheng-ubuntu:~/workspace/httpclient$ sudo nc -l -p 80

[sudo] password for linbc:

POST /a.b HTTP/1.1

Accept: image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/vnd.ms-xpsdocument, application/xaml+xml, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint,
*/*

Accept-Language: zh-cn

Content-Type: application/x-www-form-urlencoded

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618)

Host: 192.168.1.103

Content-Length: 12

Connection: Keep-Alive

Cache-Control: no-cache

input1=hello

好了,基本上知道post请求的http头

下面直接看代码

#include "tuobao_tcpclient.h"

int http_post(tuobao_tcpclient *pclient,char *page,char *request,char **response){

char post[300],host[100],content_len[100];

char *lpbuf,*ptmp;

int len=0;

lpbuf = NULL;

const char *header2="User-Agent: Tuobao Http 0.1\r\nCache-Control: no-cache\r\nContent-Type: application/x-www-form-urlencoded\r\nAccept: */*\r\n";

sprintf(post,"POST %s HTTP/1.0\r\n",page);

sprintf(host,"HOST: %s:%d\r\n",pclient->remote_ip,pclient->remote_port);

sprintf(content_len,"Content-Length: %d\r\n\r\n",strlen(request));

len = strlen(post)+strlen(host)+strlen(header2)+strlen(content_len)+strlen(request)+1;

lpbuf = (char*)malloc(len);

if(lpbuf==NULL){

return -1;

}

strcpy(lpbuf,post);

strcat(lpbuf,host);

strcat(lpbuf,header2);

strcat(lpbuf,content_len);

strcat(lpbuf,request);

if(!pclient->connected){

tuobao_tcpclient_conn(pclient);

}

if(tuobao_tcpclient_send(pclient,lpbuf,len)<0){

return -1;

}

printf("发送请求:\n%s\n",lpbuf);

/*释放内存*/

if(lpbuf != NULL) free(lpbuf);

lpbuf = NULL;

/*it's time to recv from server*/

if(tuobao_tcpclient_recv(pclient,&lpbuf,0) <= 0){

if(lpbuf) free(lpbuf);

return -2;

}

printf("接收响应:\n%s\n",lpbuf);

/*响应代码,|HTTP/1.0 200 OK|

*从第10个字符开始,第3位

* */

memset(post,0,sizeof(post));

strncpy(post,lpbuf+9,3);

if(atoi(post)!=200){

if(lpbuf) free(lpbuf);

return atoi(post);

}

ptmp = (char*)strstr(lpbuf,"\r\n\r\n");

if(ptmp == NULL){

free(lpbuf);

return -3;

}

ptmp += 4;/*跳过\r\n*/

len = strlen(ptmp)+1;

*response=(char*)malloc(len);

if(*response == NULL){

if(lpbuf) free(lpbuf);

return -1;

}

memset(*response,0,len);

memcpy(*response,ptmp,len-1);

/*从头域找到内容长度,如果没有找到则不处理*/

ptmp = (char*)strstr(lpbuf,"Content-Length:");

if(ptmp != NULL){

char *ptmp2;

ptmp += 15;

ptmp2 = (char*)strstr(ptmp,"\r\n");

if(ptmp2 != NULL){

memset(post,0,sizeof(post));

strncpy(post,ptmp,ptmp2-ptmp);

if(atoi(post)<len)

(*response)[atoi(post)] = '\0';

}

}

if(lpbuf) free(lpbuf);

return 0;

}

int main(){

tuobao_tcpclient client;

char *response = NULL;

printf("开始组包\n");

tuobao_tcpclient_create(&client,"127.0.0.1",80);

if(http_post(&client,"/i.php","f1=hello",&response)){

printf("失败!\n");

exit(2);

}

printf("响应:\n%d:%s\n",strlen(response),response);

free(response);

return 0;

}

写个简单的makefile

objects = tuobao_tcpclient.o httppost.o

httppost: $(objects)

cc -o httppost $(objects)

tuobao_tcpclient.o: tuobao_tcpclient.h

httppost.o:

.PHONY : clean

clean :

@echo 正在移除

-rm httppost $(objects)

好了,万事OK了。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: