C++如何监听http请求

来源:互联网 发布:淘宝店运动壹号怎么样 编辑:程序博客网 时间:2024/06/07 02:54
下面有个例子,基于 Windows 的,编译完,运行 : WebSrv 7070 即可。在程序的目录中放一个 index.html 文件。/************************************************************************* *  * Copyright (c) 2002-2005 by Zhang Huiyong All Rights Reserved * * FILENAME:  WebSrv.c * * PURPOSE :  HTTP 服务器程序, 向客户端提供请求的文件内容. *   * AUTHOR  :  张会勇 *  * BOOK    :  <<WinSock网络编程经络>> *  **************************************************************************/#include <stdio.h>#include <winsock2.h>#pragma comment(lib, "ws2_32.lib")  /* WinSock使用的库函数 *//* 定义常量 */#define HTTP_DEF_PORT        80     /* 连接的缺省端口 */#define HTTP_BUF_SIZE      1024     /* 缓冲区的大小 */#define HTTP_FILENAME_LEN   256     /* 文件名长度 *//* 定义文件类型对应的 Content-Type */struct doc_type{    char *suffix; /* 文件后缀 */    char *type;   /* Content-Type */};struct doc_type file_type[] = {    {"html",    "text/html"  },    {"gif",     "image/gif"  },    {"jpeg",    "image/jpeg" },    { NULL,      NULL        }};char *http_res_hdr_tmpl = "HTTP/1.1 200 OK\r\nServer: Huiyong's Server <0.1>\r\n"    "Accept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: close\r\n"    "Content-Type: %s\r\n\r\n";/************************************************************************** * * 函数功能: 根据文件后缀查找对应的 Content-Type. * * 参数说明: [IN] suffix, 文件名后缀; * * 返 回 值: 成功返回文件对应的 Content-Type, 失败返回 NULL. * **************************************************************************/char *http_get_type_by_suffix(const char *suffix){    struct doc_type *type;    for (type = file_type; type->suffix; type++)    {        if (strcmp(type->suffix, suffix) == 0)            return type->type;    }    return NULL;}/************************************************************************** * * 函数功能: 解析请求行, 得到文件名及其后缀. 请求行格式: *           [GET http://www.baidu.com:8080/index.html HTTP/1.1] * * 参数说明: [IN]  buf, 字符串指针数组; *           [IN]  buflen, buf 的长度; *           [OUT] file_name, 文件名; *           [OUT] suffix, 文件名后缀; * * 返 回 值: void. * **************************************************************************/void http_parse_request_cmd(char *buf, int buflen, char *file_name, char *suffix){    int length = 0;    char *begin, *end, *bias;    /* 查找 URL 的开始位置 */    begin = strchr(buf, ' ');    begin += 1;            /* 查找 URL 的结束位置 */    end = strchr(begin, ' ');    *end = 0;    bias = strrchr(begin, '/');    length = end - bias;    /* 找到文件名的开始位置 */    if ((*bias == '/') || (*bias == '\\'))    {        bias++;        length--;    }    /* 得到文件名 */    if (length > 0)    {        memcpy(file_name, bias, length);        file_name[length] = 0;        begin = strchr(file_name, '.');        if (begin)            strcpy(suffix, begin + 1);    }}/************************************************************************** * * 函数功能: 向客户端发送 HTTP 响应. * * 参数说明: [IN]  buf, 字符串指针数组; *           [IN]  buf_len, buf 的长度; * * 返 回 值: 成功返回非0, 失败返回0. * **************************************************************************/int http_send_response(SOCKET soc, char *buf, int buf_len){    int read_len, file_len, hdr_len, send_len;    char *type;    char read_buf[HTTP_BUF_SIZE];    char http_header[HTTP_BUF_SIZE];    char file_name[HTTP_FILENAME_LEN] = "index.html", suffix[16] = "html";    FILE *res_file;    /* 得到文件名和后缀 */    http_parse_request_cmd(buf, buf_len, file_name, suffix);    res_file = fopen(file_name, "rb+"); /* 用二进制格式打开文件 */    if (res_file == NULL)    {        printf("[Web] The file [%s] is not existed\n", file_name);        return 0;    }    fseek(res_file, 0, SEEK_END);    file_len = ftell(res_file);    fseek(res_file, 0, SEEK_SET);        type = http_get_type_by_suffix(suffix); /* 文件对应的 Content-Type */    if (type == NULL)    {        printf("[Web] There is not the related content type\n");        return 0;    }    /* 构造 HTTP 首部,并发送 */    hdr_len = sprintf(http_header, http_res_hdr_tmpl, file_len, type);    send_len = send(soc, http_header, hdr_len, 0);    if (send_len == SOCKET_ERROR)    {        fclose(res_file);        printf("[Web] Fail to send, error = %d\n", WSAGetLastError());        return 0;    }    do /* 发送文件, HTTP 的消息体 */    {        read_len = fread(read_buf, sizeof(char), HTTP_BUF_SIZE, res_file);        if (read_len > 0)        {            send_len = send(soc, read_buf, read_len, 0);            file_len -= read_len;        }    } while ((read_len > 0) && (file_len > 0));    fclose(res_file);        return 1;}int main(int argc, char **argv){    WSADATA wsa_data;    SOCKETsrv_soc = 0, acpt_soc;  /* socket 句柄 */    struct sockaddr_in serv_addr;   /* 服务器地址  */    struct sockaddr_in from_addr;   /* 客户端地址  */    char recv_buf[HTTP_BUF_SIZE];    unsigned short port = HTTP_DEF_PORT;    unsigned long from_len = sizeof(from_addr);    intresult = 0, recv_len;    if (argc == 2) /* 端口号 */        port = atoi(argv[1]);    WSAStartup(MAKEWORD(2,0), &wsa_data); /* 初始化 WinSock 资源 */        srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */    if (srv_soc == INVALID_SOCKET)    {        printf("[Web] socket() Fails, error = %d\n", WSAGetLastError());        return -1;     }        /* 服务器地址 */    serv_addr.sin_family = AF_INET;    serv_addr.sin_port = htons(port);    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);    result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));    if (result == SOCKET_ERROR) /* 绑定失败 */    {        closesocket(srv_soc);        printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());        return -1;     }    result = listen(srv_soc, SOMAXCONN);    printf("[Web] The server is running ... ...\n");    while (1)    {        acpt_soc = accept(srv_soc, (struct sockaddr *) &from_addr, &from_len);        if (acpt_soc == INVALID_SOCKET) /* 接受失败 */        {            printf("[Web] Fail to accept, error = %d\n", WSAGetLastError());            break;         }        printf("[Web] Accepted address:[%s], port:[%d]\n",             inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));        recv_len = recv(acpt_soc, recv_buf, HTTP_BUF_SIZE, 0);        if (recv_len == SOCKET_ERROR) /* 接收失败 */        {            closesocket(acpt_soc);            printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());            break;         }        recv_buf[recv_len] = 0;        /* 向客户端发送响应数据 */        result = http_send_response(acpt_soc, recv_buf, recv_len);        closesocket(acpt_soc);    }        closesocket(srv_soc);    WSACleanup();    printf("[Web] The server is stopped.\n");    return 0;}
0 0
原创粉丝点击