现在的位置: 首页 > 综合 > 正文

如何利用socket进行HTTP访问

2014年11月18日 ⁄ 综合 ⁄ 共 2361字 ⁄ 字号 评论关闭
如何利用

socket

进行

HTTP

访问
平常我们要访问某个
URL
一般都是通过浏览器进行:提交一个
URL
请求后,浏览器将请求发向目标服务器或者代理服务器,目标服务器或者代理服务器返回我们所需要的数据,浏览器接收到这些数据后保存成文件并进行显示。
下面我们看看如何自己利用
winsock2.h
中的接口来实现这个功能?为了简化问题,作以下假设:
通过代理服务器进行
HTTP
访问,这样就省去了对
URL
进行
DNS
解析的步骤,假设代理服务器的地址为:
192.168.0.1

808
 
这个功能由以下几个部分组成:
1. 
如何建立连接?
2. 
如何发送请求?
3. 
如何接收数据?
4. 
如何判断数据接收完成?
 
下面我们依次来看下这些问题如何解决?
一、

如何建立与服务器之间的连接
HTTP
基本
TCP
,所以我们需要与服务器建立连接,然后才能发送数据。
建立连接参考如下函数
socket_open
/*
*
打开Socket,返回socketId,-1表示失败
*/
int
socket_open(int
IP,int
Port,int
type){
SOCKET socketId;
 struct
sockaddr_in serv_addr;
  int
status;
 
 socketId=socket(AF_INET,SOCK_STREAM,0);
 
 if
((int
)socketId<0)
 {
       printf("[ERROR]Create a socket failed!/n"
);
       return
-1;
 }
 
 memset(&serv_addr,0,sizeof
(serv_addr));
 serv_addr.sin_family=AF_INET;
 serv_addr.sin_addr.s_addr = ntohl(IP);
 serv_addr.sin_port = htons((USHORT)Port);
 status=connect(socketId,(struct
sockaddr*)&serv_addr,sizeof
(serv_addr));
    if
(status!=0)
 {
    printf("[ERROR]Connecting failed!/n"
);
    closesocket(socketId);
    return
-1;
 }
 return
socketId;
}
        
调用方式如下:
int
socketId=socket_open(
0xC0A80001,808,0); //0xC0A80001

是192.168.0.1的十六进制写法。
二、

如何发送请求
发送数据要根据
HTTP
协议的要求附加协议头:
static
const
char
* protocolHead="GET http://www.xxx.com/index.html HTTP/1.1/n"
     "Accept:
image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword, */*/n"

     "Accept-Language: zh-cn/n"
     "User-Agent:iPanelBrowser/2.0/n"
     "Host: www.xxx.com:80/n"
     "Connection: close/n/n"
    
这里使用GET来获取指定URL的指定文档。
    
建立连接后使用send将这些数据发送出去:
     send(socketId, protocolHead,strlen(protocolHead),0);
    
发送完成HTTP请求后就等待接收数据。
      
三、

如何接收数据
这里采用
select
循环查询的方式来判断有无数据到来:
 
struct
timeval tm = {0,7};
     fd_set fds_r;
     int
status;
     char recvBuf[4096]={

/0’};
     FD_ZERO(&fds_r);
     FD_SET(socketId,&fds_r);
    
status=select(socketId+ 1, &fds_r, 0, 0, &tm); //socketId

在这里是最大的fd
    
     if
(status > 0 && FD_ISSET(socketId, &fds_r))
{
         printf("Socket is readable...fd=[%d]/n"
,socketId);
          recv(socketId,recvBuf,4096,0);
}
 
这样数据包就保存到缓冲区中了。
 
四、

如何判断数据接收完成
首先对返回数据的状态进行判断,仅当状态为“
HTTP 200 OK
”时才表明正确返回,这时才对数据进行解析并保存,如果状态为
HTTP 404 NOT FOUND
或者其它状态则表明没有找到资源或者出现其它问题,可参考
HTTP 1.1状态代码及其含义


当数据正确返回时,为了将实际数据从协议中分离出来进行保存,需要对
HTTP
数据包进行解析得到
Content-Length
,然后在包含
Content-Length
的当前数据包或者随后的数据包中查找第一个空行,这就是内容(
Content
)的开始位置,再配合前面解析得到的
Content-Length
,就能够知道什么时候数据接收完成了。换行符为“
/r/n
”,也兼容“
/n
”或者“
/r
”,设换行符为
^P
,则空行如果位于内容中间或结尾则可查找“
^P^P
”,若位于开头,则查找
^P
 
基本就是上面这些,这四个问题解决了,那么整个问题也就解决了!
【上篇】
【下篇】

抱歉!评论已关闭.