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

#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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 下面为Daytime这个服务的源代码例子,同时兼容IPV6和IPV4的地址,最后部分有更多说明。 单播模式下的Se...
    天楚锐齿阅读 5,849评论 0 2
  • 大纲 一.Socket简介 二.BSD Socket编程准备 1.地址 2.端口 3.网络字节序 4.半相关与全相...
    VD2012阅读 2,500评论 0 5
  • 网络编程基础网络编程,首先了解计算机网络体系结构是有必要的,着重掌握TCP、IP协议,理解socket的概念,理解...
    zhile_doing阅读 1,876评论 0 1
  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom阅读 2,736评论 0 3
  • 网络模型 物理层 物理层表示的是比特流传输,通常包括串口/COM口、并行/LPT口、USB、网线接口、电话线接口;...
    秋风弄影阅读 761评论 0 2