SOCKET模擬HTTP請求
HTTP請求頭部樣例:
GET http://www.baidu.com/ HTTP/1.1
Accept: html/text
Host: 220.181.6.175:80
Connection: Close
這是一個請求百度頁面的頭部。
屬性和值的命名中間用:和空格隔開,結尾使用\r\n,頭部結束使用\r\n\r\n
GET表示採用GET方法,當然我們常見的還有POST等其他方法,具體每個方法的意義可以檢視RFC文件(附件)。
http://www.baidu.com/請求URL的絕對地址,如果使用相對地址可以改為/或者/index.html.注:後面的/不能少。
HTTP/1.1 版本號
Accept 接受響應的型別
Host請求的主機地址和埠
Connection:如果值為close則告訴伺服器,當本次資料傳遞完畢以後,就會斷開TCP連結。如果值為Keep-Alive則告訴伺服器,資料傳輸結束後,本次連結不斷開,等待後續請求。
用SOCKET模擬遞交HTTP請求步驟:
1.首先建立和HTTP伺服器的TCP連結
2.組織HTTP請求
3.傳送請求
4.獲取響應
一個下載百度首頁的例子:
#include "stdlib.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netdb.h"
#include "string.h"
#include "arpa/inet.h"
#include "ctype.h"
#include "stdio.h"
#include "sys/stat.h"
#include "fcntl.h"
void send_and_recv(int sockfd, char * url, char * fun_type, char * accept_type,
char * ip, int port, char * file_loc, char * body, char * connection_type);
//sockfd表示TCP連結的套接字,url請求服務的相對或者絕對地址,fun_type請求方法,accept_type接受類 型,ip,port請求的伺服器的地址和埠,file_loc下載檔案存放位置,body請求的主體,connection_type用來指定 connection的型別
int main() {
int sockfd;
struct sockaddr_in serv_socket;
int port = 80;
char ip[] =
"220.181.6.175"; //ip地址,可以通過gethostbyname來獲取
char file_loc[] =
"/programe/http/temp.html"; //下載的存放位置
bzero(&serv_socket,
sizeof(struct sockaddr_in));
serv_socket.sin_family = AF_INET;
serv_socket.sin_port = htons(port);
inet_pton(AF_INET, ip,
&serv_socket.sin_addr);
sockfd = socket(AF_INET, SOCK_STREAM,
0);
int flag = connect(sockfd, (struct
sockaddr *)&serv_socket, sizeof(serv_socket)); //建立和HTTP伺服器的TCP連結
if(flag < 0) {
printf("connect error!!! flag = %d\n", flag);
exit(1);
}
send_and_recv(sockfd,
"http://www.baidu.com/", "GET", "html/text", ip,
port, file_loc, NULL, "Close"); //下載的主體函式
close(sockfd);
exit(0);
}
void send_and_recv(int sockfd, char * url, char * fun_type, char * accept_type,
char * ip, int port, char * file_loc, char * body, char * connection_type) {
char * request = (char *) malloc (4
* 1024 * sizeof(char));
if(body)
sprintf(request, "%s %s HTTP/1.1\r\nAccept: %s\r\nHost:
%s:%d\r\nConnection: %s\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-L
ength: %d\r\n\r\n%s", fun_type, url, accept_type, ip, port,
connection_type, body, strlen(body));
else
sprintf(request, "%s %s HTTP/1.1\r\nAccept: %s\r\nHost:
%s:%d\r\nConnection: %s\r\n\r\n", fun_type, url, accept_type, ip, port,
connection_type
);
//以上是在組織請求的頭部,列印出的結果就是文章開頭所寫
int send = write(sockfd, request,
strlen(request));
printf("%s", request);
free(request);
char * response = (char *) malloc
(1024 * sizeof(char));
if(file_loc) {
int file = open(file_loc, O_RDWR | O_APPEND);
int length;
do {
length = read(sockfd, response, 1024);
char * loc = strstr(response, "\r\n\r\n"); //截獲返回頭部,以\r\n\r\n為標識
if(loc) {
int loci = loc - response + 4;
write(1, response, loci);//如果是響應頭部就列印至螢幕
write(file, loc, length - loci);//如果是響應主體就寫入檔案
} else {
write(file, response, length);
}
if(!length)//注意,因為之前採用的是close方法,也就是說一旦傳輸資料完畢,則伺服器端會斷開連結,則read函式會返回0,所以這裡 會退出迴圈。如果採用的是Keep-Alive則伺服器不關閉TCP連結,也就說程式將會被阻塞在read函式中,因此要注意的是自己判斷是否讀到了響應 的結尾,然後在再次呼叫read之前退出迴圈。
break;
} while(1);
close(file);
} else {
int length;
do {
length = read(sockfd, response, 1024);
printf("%s", response);
if(!length)
break;
} while(1);
}
free(response);
}
之前的頭部比較簡單,在傳送請求的時候,我們常常會遞交表單,如果採用GET方法,則可以通過URL傳遞引數。如果採用POST,則新的HTTP請求看上去應該是這樣。(帶COOKIE)
POST http://192.168.1.154:8888/httpstudy2/servlet/IndexServlet HTTP/1.1
Accept: html/text
Host: 192.168.1.154:8888
Cookie: username=difa; password=yuna
Connection: Close
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=hello&password=world
Content-Type表示主體型別
Content-Length表示主體長度,不包括頭部。
整個傳送的HTTP請求應該是:
POST http://192.168.1.154:8888/httpstudy2/servlet/IndexServlet HTTP/1.1\r\nAccept: html/text\r\nHost: 192.168.1.154:8888\r\nCookie: username=difa; password=yuna\r\nConnection: Close\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 29\r\n\r\nusername=hello&password=world
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25897606/viewspace-704825/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python 使用socket模擬http請求,從阻塞到協程PythonHTTP
- 使用 Netcat 模擬 HTTP 請求HTTP
- C#模擬HTTP請求Post JSONC#HTTPJSON
- ASP.NET Core擴充套件庫之Http請求模擬ASP.NET套件HTTP
- 使用 node 模擬請求介面
- Jmeter —— jmeter設定HTTP資訊頭管理器模擬請求頭JMeterHTTP
- php模擬請求(偽造來源和請求ip)PHP
- 使用Socket進行HTTP請求與報文講解HTTP
- SQL Server儲存過程模擬HTTP請求POST和GET協議SQLServer儲存過程HTTP協議
- http請求HTTP
- HTTP 請求HTTP
- Linux curl 命令模擬 POST/GET 請求Linux
- 使用postman模擬登陸post請求方法Postman
- 使用Mock.js模擬資料請求MockJS
- 模擬介面請求到web伺服器Web伺服器
- http請求概述HTTP
- HTTP請求方法HTTP
- http請求頭HTTP
- go http請求GoHTTP
- Node.js模擬發起http請求從非同步轉同步的5種方法Node.jsHTTP非同步
- 合併HTTP請求vs並行HTTP請求,到底誰更快?HTTP並行
- 合併HTTP請求 vs 並行HTTP請求,到底誰更快?HTTP並行
- Cookie 與 HTTP請求CookieHTTP
- Jsoup http請求JSHTTP
- Android Http請求AndroidHTTP
- HTTP請求報文HTTP
- Java,InputStream,Socket阻塞.(關於HTTP請求的IO問題自我總結)JavaHTTP
- axios模擬GET請求例項及詳解iOS
- 【轉】怎麼用PHP傳送HTTP請求(POST請求、GET請求)?PHPHTTP
- HTTP的請求過程HTTP
- python做http請求PythonHTTP
- Http請求資料格式HTTP
- HTTP GET請求傳bodyHTTP
- golang 的 http 請求池GolangHTTP
- HTTP 請求與響應HTTP
- Java實現Http請求JavaHTTP
- go http請求流程分析GoHTTP
- 七種HTTP請求方法HTTP