c++实现简单http服务器

来源:互联网 发布:银天下太极线指标源码 编辑:程序博客网 时间:2024/06/11 03:01

http基于tcp协议的应用层协议,说白了就是写死的自定义协议,代码实现了简单的get请求,打开服务后,可以通过网站访问本地资源,适合新手学习的简单代码,有助于理解get和http报文,很简单

HttpService.h
#ifndef HTTP_SERVICE#define HTTP_SERVICE#include <stdio.h>#include <winsock2.h>#include <iostream> #pragma comment(lib, "ws2_32.lib")  /* WinSock使用的库函数 */  /* 定义常量 */#define HTTP_PORT 6080 /* 连接的缺省端口 */#define HTTP_BUF_SIZE 1024 /* 缓冲区的大小 */#define HTTP_FILENAME_LEN 999 /* 文件名长度 */#defineHTTP_FILEEXTENSION_LEN 20//文件后缀长度#defineHTTP_CMD_LEN 20//命令长度/* 定义文件类型对应的 Content-Type */struct FileExtension{    char * pExtensive; /* 文件后缀 */    char * pType;/* Content-Type */}; class HttpService{public:char cRecvBuffer[HTTP_BUF_SIZE];//缓存请求命令protected:char cRecvFile[HTTP_FILENAME_LEN];//请求文件char cExtensive[HTTP_FILEEXTENSION_LEN];//文件后缀char cHttpCmd[HTTP_CMD_LEN];public:HttpService();~HttpService();public:void AnalyRecvBuffer();void HttpResponse(SOCKET sSocket);protected:void Cmd_Get(SOCKET sSocket);void Cmd_Post(SOCKET sSocket);char *AnalyExtensive();};#endif;




httpService类实现

HttpService.cpp

#include "HttpService.h"char * pHttpHead = "HTTP/1.1 200 OK\r\nDate:%s\r\nServer: ZhaoYueYou's Server \r\n"    "Accept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: close\r\n"    "Content-Type: %s\r\n\r\n";struct FileExtension FileType[] = {{"html",    "text/html"  },{"gif",     "image/gif"  },{"jpeg",    "image/jpeg" },{"jpg",     "image/jpeg" },{"png","image/png"},{ "js","text/javascript"},{"css","text/css"},{"txt","text/plain"},{"mp4","video/mp4"},{ NULL,      NULL        }};HttpService::HttpService(){memset(cRecvBuffer,0,HTTP_BUF_SIZE);memset(cRecvFile,0,HTTP_FILENAME_LEN);memset(cExtensive,0,HTTP_FILEEXTENSION_LEN);memset(cHttpCmd,0,HTTP_CMD_LEN); }HttpService::~HttpService(){}void HttpService::AnalyRecvBuffer(){int nLength = 0;    char *pBegin;char *pEnd;char *pFile;intnHeadLen = 0;     /* 查找 URL 的开始位置 */    pBegin = strchr(cRecvBuffer, ' ');nHeadLen =  pBegin-cRecvBuffer;if(nHeadLen<HTTP_CMD_LEN && nHeadLen>0)  memcpy(cHttpCmd, cRecvBuffer, nHeadLen);elsestd::cout<<"命令头长度异常 "<<std::endl;    pBegin += 1;             /* 查找 URL 的结束位置 */    pEnd = strchr(pBegin, ' ');    *pEnd = 0;     pFile = strchr(pBegin, '/');    nLength = pEnd - pFile;     /* 找到文件名的开始位置 */    if ((*pFile == '/') || (*pFile == '\\'))    {        pFile++;        nLength--;    }    /* 得到文件名 */    if (nLength > 0 && nLength <HTTP_FILENAME_LEN )    {        memcpy(cRecvFile, pFile, nLength);        cRecvFile[nLength] = 0;         pBegin = strchr(cRecvFile, '.');int nExtensiveLen = pEnd-pBegin;        if (pBegin && nExtensiveLen<HTTP_FILEEXTENSION_LEN)            strcpy(cExtensive, pBegin + 1);elsestd::cout<<"后缀长度异常 "<<std::endl;    }elsestd::cout<<"文件长度异常 "<<std::endl;}void HttpService::HttpResponse(SOCKET sSocket){if(!strcmp(cHttpCmd,"GET"))Cmd_Get(sSocket);else if(!strcmp(cHttpCmd,"POST"))Cmd_Post(sSocket);else{std::cout<<"其他命令 "<<cHttpCmd<<std::endl;}}void HttpService::Cmd_Get(SOCKET sSocket){int nHttpHeadLen =0;intnFileLen = 0;int nSendLen = 0;int nRendLen = 0;char cReadBuf[HTTP_FILENAME_LEN] = {0};FILE *pFile;char *pFileType;    pFile = fopen(cRecvFile, "rb+"); /* 用二进制格式打开文件 */    if (pFile == NULL)    {        printf("[Web] The file [%s] is not existed\n", cRecvFile);        return ;    }fseek(pFile, 0, SEEK_END);    nFileLen = ftell(pFile);    fseek(pFile, 0, SEEK_SET);pFileType = AnalyExtensive();if (pFileType == NULL)    {        printf("[Web] There is not the related content type\n");        return ;    }SYSTEMTIME sys;   GetLocalTime( &sys );   char ptr[40]={0};sprintf( ptr,"%4d/%02d/%02d %02d:%02d:%02d.%03d ",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute, sys.wSecond,sys.wMilliseconds,sys.wDayOfWeek);    /* 构造 HTTP 首部,并发送 */char HttpHeader[HTTP_FILENAME_LEN]={0};    nHttpHeadLen = sprintf(HttpHeader, pHttpHead,ptr, nFileLen, pFileType);    nSendLen = send(sSocket, HttpHeader, nHttpHeadLen, 0);std::cout<<HttpHeader<<std::endl;    //send_len=1;    if (nSendLen == SOCKET_ERROR)    {        fclose(pFile);        printf("[Web] Fail to send, error = %d\n", WSAGetLastError());        return ;    }     do /* 发送文件, HTTP 的消息体 */    {        nRendLen = fread(cReadBuf, sizeof(char), HTTP_FILENAME_LEN, pFile);         if (nRendLen > 0)        {            nSendLen = send(sSocket, cReadBuf, nRendLen, 0);            nFileLen -= nRendLen;        }    } while ((nRendLen > 0) && (nFileLen > 0));     fclose(pFile);}void HttpService::Cmd_Post(SOCKET sSocket){}char *HttpService::AnalyExtensive(){   struct FileExtension *pType;    for (pType = FileType; pType->pExtensive; pType++)    {        if (strcmp(pType->pExtensive, cExtensive) == 0)return pType->pType;    }     return NULL;}

入口 main

 

#include "HttpService.h"void main(){WSADATA wsa_data;    SOCKET  srv_soc = 0, acpt_soc;  /* socket 句柄 */    struct sockaddr_in serv_addr;   /* 服务器地址  */    struct sockaddr_in from_addr;   /* 客户端地址  */    unsigned short port = HTTP_PORT;    int from_len = sizeof(from_addr);int result = 0,recv_len = 0;    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());system("pause");        return ;     }         /* 服务器地址 */    serv_addr.sin_family = AF_INET;    serv_addr.sin_port = htons(port);    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_pton(AF_INET,"180.173.168.61",&serv_addr.sin_addr.s_addr);     result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));    if (result == SOCKET_ERROR) /* 绑定失败 */    {        closesocket(srv_soc);perror("bind:");        printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());system("pause");        return ;     }     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());system("pause");            break;         }               printf("[Web] Accepted address:[%s], port:[%d]\n",             inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port)); HttpService hService;recv_len = recv(acpt_soc, hService.cRecvBuffer, HTTP_BUF_SIZE, 0);        if (recv_len == SOCKET_ERROR) /* 接收失败 */        {            closesocket(acpt_soc);            printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());system("pause");            break;         }         hService.cRecvBuffer[recv_len] = 0;hService.AnalyRecvBuffer();hService.HttpResponse(acpt_soc);closesocket(acpt_soc);}closesocket(srv_soc);    WSACleanup();    printf("[Web] The server is stopped.\n");     return ; }


1 0
原创粉丝点击