搭建内网服务器
正文
// httpServer.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include<windows.h>
#include<io.h>
#include<bits/stdc++.h>
//要使用网络编程,要包含系统给我们提供的头文件
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
void sendHtml(SOCKET clifd, const char* filePath);
void notFound404(SOCKET clifd);
void notFound403(SOCKET clifd);
//输出错误代码,并返回输出码
void error_die(const char* str) {
printf("[hint]%s failed:%d", str,WSAGetLastError());//获取错误码
exit(-1);
}
//初始化
void initSocket() {
// 参数1.指定socket版本 参数2.是一个传出参数
WORD version = MAKEWORD(2, 2);
WSADATA wsadata;
if (0 != WSAStartup(version, &wsadata)) {
error_die("WSAStartup");
}
}
SOCKET listenClient(){
//2.创建socket
//参数1.指定IP协议 ipv4(AF_INET) ipv6(AF_INET6)
//参数2.数据传输格式,常见的有两种,流式传输和数据报传输
//参数3.传输协议, TCP 和 UDP
SOCKET serfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serfd == INVALID_SOCKET) {
error_die("socket");
}
//3.绑定IP地址和端口号
//参数1.指定的socket
//参数2.IP地址和端口号
//参数3.
struct sockaddr_in serAddr;
/*
typedef struct sockaddr_in {
USHORT sin_port;
IN_ADDR sin_addr;
CHAR sin_zero[8];
} SOCKADDR_IN, *PSOCKADDR_IN;
*/
serAddr.sin_family = AF_INET;//必须和创建socket的时候一样
//大端存储--一般网络和小端存储--一般计算机,htons把本地字节序转为网络字节序
serAddr.sin_port = htons(80); //[0-65535) 0-1024是系统保留端口号,一般不用,80是http服务器专用
serAddr.sin_addr.S_un.S_addr = INADDR_ANY;//绑定本机任意服务器
if (SOCKET_ERROR == bind(serfd, (struct sockaddr*)&serAddr, sizeof(serAddr))) {
error_die("bind");
}
//4.监听
listen(serfd, 10);
return serfd;
}
void accept_request(SOCKET clifd) {
//从clifd接受数据
char recvBuf[1024] = "";
if (recv(clifd, recvBuf, sizeof(recvBuf), 0)<=0) {
error_die("recv offline");
}
SYSTEMTIME st;//定义本地时间变量,该变量为结构体
GetLocalTime(&st);//获取本地时间函数,参数为时间变量指针
cout<<"time:"<<st.wYear<<"年"<<st.wMonth<<"月"<<st.wDay<<"日"<<st.wHour<<"时"<<st.wMinute<<"分"<<st.wSecond<<"秒"<<endl;
std::cout<<"recvBuf:";
cout<<recvBuf<<std::endl;
fstream r1;//保存日志
r1.open("日志.txt",ios::app);
r1<<"have a new connect...\ntime:"<<st.wYear<<"年"<<st.wMonth<<"月"<<st.wDay<<"日"<<st.wHour<<"时"<<st.wMinute<<"分"<<st.wSecond<<"秒"<<'\n'<<recvBuf<<endl;
fstream cache;
cache.open("cache.txt",ios::out);
cache<<recvBuf;
cache.close();
cache.clear();
cache.open("cache.txt");
string a;
getline(cache,a);
//直接给客户端发送文本
char filePath[128] = "";
string b="";
for(int i=4;i<a.size()-9;i++){
b+=a[i];
}
cache.close();
cache.clear();
//选择一个网页发送
strcpy(filePath,&("htmlFiles"+b)[0]);
//判断文件是否存在
if (access(filePath,0)==0) {//0代表文件是否存在 如果存在返回0,否则返回-1
//发送网页
sendHtml(clifd, filePath);
}
else {
//发送404 not found网页
notFound404(clifd);
}
}
void sendHtml(SOCKET clifd, const char * filePath) {
FILE* pr = fopen(filePath, "r");
if (pr==NULL) {
//error_die("fopen");
notFound403(clifd);
}
char data[1024] = "";
do {
fgets(data, 1024, pr);
send(clifd, data, strlen(data), 0);
} while (!feof(pr));
fclose(pr);
}
void notFound404(SOCKET clifd) {
//发送错误
char sendData[1024] = "<html><body><p>hjsxhst2022的服务器</p></body></html>";
send(clifd, sendData, strlen(sendData), 0);
char sendBuf[1024];
sprintf(sendBuf,"HTTP/1.0 404 爆炸啦~\r\n");
send(clifd, sendBuf, strlen(sendBuf), 0);
}
void notFound403(SOCKET clifd) {
//发送错误
char sendData[1024] = "<html><body><p>hjsxhst2022的服务器</p></body></html>";
send(clifd, sendData, strlen(sendData), 0);
char sendBuf[1024];
sprintf(sendBuf,"HTTP/1.0 403 爆炸啦~\r\n");
send(clifd, sendBuf, strlen(sendBuf), 0);
}
int main()
{
//1.初始化网络库wsa windows socket ansyc->windows异步套接字
initSocket();
SOCKET serfd = listenClient();
printf("hjsxhst2022的http服务器!\n");
//5.接收链接
struct sockaddr_in cliAddr;
int len = sizeof(cliAddr);
while (1) {
SOCKET clifd = accept(serfd, (struct sockaddr*)&cliAddr, &len);//阻塞的
//SOCKET clifd = accept(serfd, NULL, NULL);
if (clifd == INVALID_SOCKET) {
error_die("accept");
}
printf("have a new connect...\n");
//6.处理链接请求
//直接给客户端发送文本
//char sendData[1024] = "<html><body><h1>zhinen丶</h1></body></html>";
//send(clifd, sendData, strlen(sendData), 0);
accept_request(clifd);
closesocket(clifd);//发送完直接关闭,http是无连接的
}
//7.关闭链接,清理网络库
closesocket(serfd);
WSACleanup();
return 0;
}
用 socket
做的,仅在内网可以访问。这里使用的是 http
协议的 $80$ 端口,如果想在外网访问的话要做一下内网穿透。上面的代码用 dev-c++ 就可以编译,只需要在工具-编译选项-编译时加入如下命令中加入:-std=c++14 -lws2_32
就可以编译了。网页文件在绝对路径下的 htmlFiles
目录中保存,现在实现了可以通过路径访问页面和记录日志的功能。更新了403炸。