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,"%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 ;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)