美文网首页
c++开启一个简单的http响应

c++开启一个简单的http响应

作者: nit小星星 | 来源:发表于2019-03-21 05:22 被阅读0次

    #include<stdio.h>

    #include<winsock2.h>

    #pragma comment(lib,"ws2_32.lib)

    #define HTTP_PORT 8080

    #define HTTP_BUFFER_SIZE 2048

    #define HTTP_FILENAME_LEN   256

    struct doc_type//定义文件类型

    {

    char *suffix;

    char *type;

    };

    struct doc_type file_type[]=

    {

      {"html",    "text/html"  },

        {"gif",     "image/gif"  },

        {"jpeg",    "image/jpeg" },

        { NULL,      NULL        }

    };

    /**************************************************************************

     *

     * 函数功能: 根据文件后缀查找对应的 Content-Type.

     *

     * 参数说明: [IN] suffix, 文件名后缀;

     *

     * 返 回 值: 成功返回文件对应的 Content-Type, 失败返回 NULL.

     *

     **************************************************************************/

    c

    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 heet_parse_request_cmd(char *buffer,int buflen,char *filename,char *suffix)

    {

    int length=0;

    char *begin,*end,*bias;

    begin=strchr(buf,' ');

    begin+=1;

    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_respone(SOCKER 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;

        }

    /* 构造 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()

    {

    WSADATA  wsa_data;

    SOCKET srv_soc,acpt_soc;

    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);

       int result = 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 */AF的意思是IP4 sock是使用sock流。0是不指定TCP还是udp。根据情况而定

     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);TCP采用大端传输的方式。这个函数就是实现大端。高字节在低地址。

        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    将主机数转换成无符号长整型的网络字节顺序。本函数将一个32位数从主机字节顺序转换成网络字节顺序。

    result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

    bind函数把一个本地的协议地址赋予一个套接字,对于网际协议。协议地址是32位de ip4或者128位的ip6与16位的tcp或者udp端口的组合。

     if (result == SOCKET_ERROR) /* 绑定失败 */

        {

            closesocket(srv_soc);

            printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());

            return -1; 

        }

     result = listen(srv_soc, SOMAXCONN);//SOMAXCONN限制系统中监听该端口的最大连接数。保存的是完成三次握手、等待accept的全连接,而不是半连接。

        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;

    }

    https://blog.csdn.net/shixin_0125/article/details/42552895

    相关文章

      网友评论

          本文标题:c++开启一个简单的http响应

          本文链接:https://www.haomeiwen.com/subject/sihfvqtx.html