如何利用socket进行HTTP访问

    技术2022-05-19  22

    如何利用 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   基本就是上面这些,这四个问题解决了,那么整个问题也就解决了!

    最新回复(0)