c++实现简单http服务器

    xiaoxiao2021-03-25  136

    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 /* 文件名长度 */ #define HTTP_FILEEXTENSION_LEN 20 //文件后缀长度 #define HTTP_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; int nHeadLen = 0; /* 查找 URL 的开始位置 */ pBegin = strchr(cRecvBuffer, ' '); nHeadLen = pBegin-cRecvBuffer; if(nHeadLen<HTTP_CMD_LEN && nHeadLen>0) memcpy(cHttpCmd, cRecvBuffer, nHeadLen); else std::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); else std::cout<<"后缀长度异常 "<<std::endl; } else std::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; int nFileLen = 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,"M/d/d d:d:d.d ",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 ; }

    转载请注明原文地址: https://ju.6miu.com/read-3595.html

    最新回复(0)