web请求的写法

来源:互联网 发布:开店软件哪个好 编辑:程序博客网 时间:2024/04/29 22:53

向指定的主机发送一个Web页面的请求。

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/times.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <time.h>

#include "web_request.h"

//使用宏来组装一份Http数据包, 此处只需要填写 get的内容,主机名
#define HTTP_HEADER  "GET /%s HTTP/1.1/r/n" /
            "User-Agent: User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2/r/n" /
            "Host: %s/r/n" /
            "Accept: text/html/r/n" /
            "Connection: Close/r/n/r/n"


/*
 * err: 本文件函数从err转换为字串
 */
const char *get_error_string(int err)
{
    if (err < 0) err = -err;
    if (err >= ERR_LAST) err = 0;
   
    return error_string[err];
}

/*
 * 根据域名及端口号,建立TCP连接
 */
static int connect_to_host(const char *host, int port)
{
    struct hostent *phe = NULL;
    struct sockaddr_in sin;
    int sock_fd;
   
    bzero(&sin, sizeof(sin));
   
    if((phe = gethostbyname(host)))
    {
        memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
    }
    else
    {
        return -ERR_RESOLVE;
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons(port);

    if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        return -ERR_SOCKET;
    }
   
    if(connect(sock_fd, (void *)&sin, sizeof(sin)) < 0)
    {
        return -ERR_CONNECT;
    }
    return sock_fd;
}

/*
 * url: 请求url,支持格式如下:
 *       www.a.com
 *       http://www.a.com:PORT     (PORT可选)
 *       http://www.a.com:PORT/b/c?d=e
 * timeout: 请求过程的超时时间,以秒为单位
 * limitsize: 读取字节限制
 * buf: web数据缓存指针
 */
int send_request(const char *url, int timeout, int limitsize, char **ppweb)
{
    char urldup[2048];
    char *host = urldup;
    char *get = "";
    char *port = "80";
   
    strncpy(urldup, url, 2048);
    urldup[2047] = 0;
   
    if(strncmp("http://", urldup, 7) == 0)
    {
        host = &urldup[7];
    }
    char *tmp = strchr(host, '/');       
    if(tmp)
    {
        *tmp = 0;                    //使host指向url的A区域。
        get = tmp + 1;                //get取到A区域后面的区域。。。
    }
   
    tmp = strchr(host, ':');               
    if(tmp)
    {
        *tmp = 0;
        port = tmp + 1;                //取端口号
    }
   
    //fprintf(stderr, "Send request: GET %s on %s, port %s/n", get, host, port);
    int np = atoi(port);                    //把字符串的端口号转化成整型数
    if(np <= 0 || np > 65535)
    {
        return -ERR_INVALIDPORT;
    }
   
    int fd = connect_to_host(host, np);        //连接到host
    if(fd < 0)
    {
        return fd;
    }
   
    int opt_tm = timeout * 1000;
    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&opt_tm, sizeof(int));
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&opt_tm, sizeof(int));
   
    char header[4096];
    int headlen = snprintf(header, 4096, HTTP_HEADER, get, host);
   
    if(send(fd, header, headlen, 0) < 0)
    {
        close(fd);
        return -ERR_SEND;
    }
   
    fd_set fdset;
    struct timeval to = { timeout, 0 };

    FD_ZERO(&fdset);
    FD_SET(fd, &fdset);

    if((select(fd + 1, &fdset, NULL, NULL, &to))< 0)
    {
        close(fd);
        return -ERR_SELECT;
    }
    if(FD_ISSET(fd, &fdset))
    {
        char *buf = malloc(limitsize + 1);
        if(!buf)
        {
            close(fd);
            return -ERR_MEMORY;
        }
        memset(buf, 0, limitsize + 1);
       
        int len = recv(fd, buf, limitsize, MSG_WAITALL);
        if(len <= 0)
        {
            free(buf);
            buf = NULL;
            close(fd);
            return -ERR_READ;
        }
        buf[len] = 0;

        *ppweb = buf;
    }

    close(fd);

    return 0;
}

 

 

错误处理:

 

#ifndef _WEB_REQUEST_H_
#define _WEB_REQUEST_H_


enum errcode {
    NOERR,
    ERR_INTERNAL,
    ERR_RESOLVE,
    ERR_SOCKET,
    ERR_CONNECT,
    ERR_INVALIDPORT,
    ERR_SEND,
    ERR_SELECT,
    ERR_MEMORY,
    ERR_READ,
   
    ERR_LAST,
};

static const char *error_string[ERR_LAST] = {
    "No error",
    "Internal error",
    "Can not recolve",
    "Socket error",
    "Connect error",
    "Invalid port",
    "Send error",
    "Select error",
    "Out of memory",
    "Read error",
};

int send_request(const char *url, int timeout, int limitsize, char **ppweb);


#endif
0 0
原创粉丝点击