如何利用socket进行HTTP访问
2011-05-20 18:27
726 查看
平常我们要访问某个URL一般都是通过浏览器进行:提交一个URL请求后,浏览器将请求发向目标服务器或者代理服务器,目标服务器或者代理服务器返回我们所需要的数据,浏览器接收到这些数据后保存成文件并进行显示。
下面我们看看如何自己利用winsock2.h中的接口来实现这个功能?为了简化问题,作以下假设:
通过代理服务器进行HTTP访问,这样就省去了对URL进行DNS解析的步骤,假设代理服务器的地址为:192.168.0.1:808。
这个功能由以下几个部分组成:
1.如何建立连接?
2.如何发送请求?
3.如何接收数据?
4.如何判断数据接收完成?
下面我们依次来看下这些问题如何解决
一、如何建立与服务器之间的连接
HTTP基本TCP,所以我们需要与服务器建立连接,然后才能发送数据。
建立连接参考如下函数socket_open:
调用方式如下
:
二、如何发送请求
发送数据要根据HTTP协议的要求附加协议头:
这里使用GET来获取指定URL的指定文档。
建立连接后使用send将这些数据发送出去:
send(socketId,protocolHead,strlen(protocolHead),0);
发送完成HTTP请求后就等待接收数据。
三、如何接收数据
这里采用select循环查询的方式来判断有无数据到来:
这样数据包就保存到缓冲区中了。
四、如何判断数据接收完成
首先对返回数据的状态进行判断,仅当状态为“HTTP200OK”时才表明正确返回,这时才对数据进行解析并保存,如果状态为HTTP404NOTFOUND或者其它状态则表明没有找到资源或者出现其它问题,可参考HTTP1.1状态代码及其含义。
当
数据正确返回时,为了将实际数据从协议中分离出来进行保存,需要对HTTP数据包进行解析得到Content-Length,然后在包含Content-
Length的当前数据包或者随后的数据包中查找第一个空行,这就是内容(Content)的开始位置,再配合前面解析得到的Content-
Length,就能够知道什么时候数据接收完成了。换行符为“/r/n”,也兼容“/n”或者“/r”,设换行符为^P,则空行如果位于内容中间或结尾则
可查找“^P^P”,若位于开头,则查找^P。
基本就是上面这些,这四个问题解决了,那么整个问题也就解决了!
摘自http://dev.firnow.com/course/3_program/c++/cppsl/2008227/101925.html
下面我们看看如何自己利用winsock2.h中的接口来实现这个功能?为了简化问题,作以下假设:
通过代理服务器进行HTTP访问,这样就省去了对URL进行DNS解析的步骤,假设代理服务器的地址为:192.168.0.1:808。
这个功能由以下几个部分组成:
1.如何建立连接?
2.如何发送请求?
3.如何接收数据?
4.如何判断数据接收完成?
下面我们依次来看下这些问题如何解决
一、如何建立与服务器之间的连接
HTTP基本TCP,所以我们需要与服务器建立连接,然后才能发送数据。
建立连接参考如下函数socket_open:
01 | /* |
02 | *打开Socket,返回socketId,-1表示失败 |
03 | */ |
04 | int socket_open( int IP, int Port, int type){ |
05 | SOCKETsocketId; |
06 | struct sockaddr_inserv_addr; |
07 | int status; |
08 |
09 | socketId=socket(AF_INET,SOCK_STREAM,0); |
10 |
11 | if (( int )socketId<0) |
12 | { |
13 | printf ( "[ERROR]Createasocketfailed!/n" ); |
14 | return -1; |
15 | } |
16 |
17 | memset (&serv_addr,0, sizeof (serv_addr)); |
18 | serv_addr.sin_family=AF_INET; |
19 | serv_addr.sin_addr.s_addr=ntohl(IP); |
20 | serv_addr.sin_port=htons(( USHORT )Port); |
21 | status=connect(socketId,( struct sockaddr*)&serv_addr, sizeof (serv_addr)); |
22 | if (status!=0) |
23 | { |
24 | printf ( "[ERROR]Connectingfailed!/n" ); |
25 | closesocket(socketId); |
26 | return -1; |
27 | } |
28 | return socketId; |
29 | } |
:
1 | int socketId=socket_open(0xC0A80001,808,0); //0xC0A80001是192.168.0.1的十六进制写法。 |
发送数据要根据HTTP协议的要求附加协议头:
1 | static const char *protocolHead= "GET |
2 | "Accept: |
3 | "Accept-Language:zh-cn/n" |
4 | "User-Agent:iPanelBrowser/2.0/n" |
5 | "Host:www.xxx.com:80/n" |
6 | "Connection:close/n/n" |
建立连接后使用send将这些数据发送出去:
send(socketId,protocolHead,strlen(protocolHead),0);
发送完成HTTP请求后就等待接收数据。
三、如何接收数据
这里采用select循环查询的方式来判断有无数据到来:
01 | struct timeval tm ={0,7}; |
02 | fd_setfds_r; |
03 | int status; |
04 | char recvBuf[4096]={‘/0’}; |
05 | FD_ZERO(&fds_r); |
06 | FD_SET(socketId,&fds_r); |
07 |
08 | status=select(socketId+1,&fds_r,0,0,& tm ); //socketId在这里是最大的fd |
09 |
10 | if (status>0&&FD_ISSET(socketId,&fds_r)) |
11 | { |
12 | printf ( "Socketisreadable...fd=[%d]/n" ,socketId); |
13 | recv(socketId,recvBuf,4096,0); |
14 | } |
四、如何判断数据接收完成
首先对返回数据的状态进行判断,仅当状态为“HTTP200OK”时才表明正确返回,这时才对数据进行解析并保存,如果状态为HTTP404NOTFOUND或者其它状态则表明没有找到资源或者出现其它问题,可参考HTTP1.1状态代码及其含义。
当
数据正确返回时,为了将实际数据从协议中分离出来进行保存,需要对HTTP数据包进行解析得到Content-Length,然后在包含Content-
Length的当前数据包或者随后的数据包中查找第一个空行,这就是内容(Content)的开始位置,再配合前面解析得到的Content-
Length,就能够知道什么时候数据接收完成了。换行符为“/r/n”,也兼容“/n”或者“/r”,设换行符为^P,则空行如果位于内容中间或结尾则
可查找“^P^P”,若位于开头,则查找^P。
基本就是上面这些,这四个问题解决了,那么整个问题也就解决了!
摘自
相关文章推荐
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- <转>如何利用socket进行HTTP访问
- <转>如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问-------------------------------http://blog.csdn.net/sanfengshou/archive/2011/03/07/6228250.aspx
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问
- 如何利用socket进行HTTP访问(转)
- 浅谈JAVA中如何利用socket进行网络编程(二)
- 如何在snap中利用socket.io及websocket来进行实时数据更新
- 浅谈JAVA中如何利用socket进行网络编程(一)