WinC++简易的web服务器

来源:互联网 发布:网络悬疑剧两小无猜 编辑:程序博客网 时间:2024/05/02 01:28





注:需建立在当前目录下的文件夹catalog,里面有img,html,txt三个文件夹,其中html文件夹包含noimg.html test.html img中包含a1.jpg txt文件夹包含test.txt

在浏览器输入http://127.0.0.1:4547/net/test.html 或http://127.0.0.1:4547/net/noimg.html 或http://127.0.0.1:4547/net/test.txt可访问

账号123,密码123

ip可直接改为你的静态ip


httpServer.h

#pragma once  #include<winsock.h>  #include<thread>struct message{char* data;bool* isActive;int clientSocket;int id;message(char* d, bool* is, int c, int i);};struct close_message{bool* isActive;int serverSocket;close_message(bool* is, int s);};class httpServer{private:enum {SERVER_PORT = 4547,BUFFER_SIZE = 13000,QUEUE_SIZE = 10,MAX = 100};char buffer[BUFFER_SIZE];sockaddr_in serverChannel;std::thread* t[MAX];std::thread* th;char rootDir[50];char name[50];bool isActive[MAX];int serverSocket; //socket  int clientSocket;friend void handleMessage(message msg);friend void listenForClose(close_message msg);public:httpServer();bool start();//开启服务器  };


httpServer.cpp

#define _CRT_SECURE_NO_WARNINGS  #include"httpServer.h"  #include<cstdio>  #include<cstdlib>  #include<fstream>  #include<cstring>  #include<string>#include<windows.h>#include<iostream>message::message(char* d, bool* is, int c, int i) :data(d), isActive(is), clientSocket(c), id(i) { }close_message::close_message(bool* is, int s) : isActive(is), serverSocket(s) { }httpServer::httpServer(){WORD wVersionRequested;WSADATA wsaData;int ret;//WinSock初始化:  wVersionRequested = MAKEWORD(2, 2);//希望使用的WinSock DLL的版本  ret = WSAStartup(wVersionRequested, &wsaData);if (ret != 0){printf("WSAStartup() failed!\n");}//确认WinSock DLL支持版本2.2:  if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();printf("Invalid Winsock version!\n");}}void sendMessage(std::string path,message msg){std::ifstream in(path, std::ios::binary);int sp;if (!in) {strcpy(msg.data, "HTTP/1.1 404 Not Found\n");printf("file no open\n");}else {in.seekg(0, std::ios_base::end);sp = in.tellg();char length[20];sprintf(length, "%d", sp);strcpy(msg.data, "HTTP/1.1 200 OK\n");strcat(msg.data, "Content-Type: text/html;charset=ISO-8859-1\nContent-Length: ");strcat(msg.data, length);strcat(msg.data, "\n\n");int total_size = 0;int r = send(msg.clientSocket, msg.data, strlen(msg.data), 0);if (r == SOCKET_ERROR) {printf("send failed\n");*msg.isActive = false;return;}else {printf("send success\n");}char buffer[100];int s = sp + strlen(msg.data) + 1;int len = sp;total_size = 0;in.clear();in.seekg(0, std::ios_base::beg);while (len > 0) {memset(buffer, 0, sizeof(buffer));int size = sizeof(buffer) < len ? sizeof(buffer) : len;total_size += size;len -= size;in.read(buffer, size);int r = send(msg.clientSocket, buffer, size, 0);if (r == SOCKET_ERROR) {printf("send failed\n");*msg.isActive = false;return;}}}}void handleMessage(message msg){int i = 0, cnt = 0;bool flag = false;bool post_flag = false;std::string str = "";std::string type = "";std::string data = "";printf("你好呀!我是线程%d\ndata = %s\n", msg.id, msg.data);if (msg.data == "" || msg.data == "\n") {*msg.isActive = false;return;}//解析http头部while (1) {if (msg.data[i] == '\n' && msg.data[i + 2] == '\n')break;if (msg.data[i] == ' ') {if (flag) {data = str;flag = false;break;}else if (str == "GET" ) {type = str;flag = true;}else if (str == "POST") {type = str;}str = "";}else if (msg.data[i] == '\n');else {str = str + msg.data[i];}i++;}if (type=="POST") {bool login_flag = false;bool pass_flag = false;std::string name = "";std::string passwd = "";str = "";for (int j = i+3; j <= strlen(msg.data); j++) {if (msg.data[j] == '&' || msg.data[j] == '=' || j ==strlen(msg.data)) {std::cout << str << std::endl;if (login_flag) {if (str == "123") {name = str;passwd = "123";}else {passwd = "";}login_flag = false;}else if (pass_flag) {if (str == passwd && str != "") {std::cout << "str="<<str << " " <<"paw="<< passwd << std::endl;char response[200];strcpy(response, "<html><body>欢迎您,");strcat(response, name.c_str());strcat(response, "!</body></html>\n");int len = strlen(response);char length[20];sprintf(length, "%d", len);strcpy(msg.data, "HTTP/1.1 200 OK\n");strcat(msg.data, "Content-Type: text/html;charset=gb2312\nContent-Length: ");strcat(msg.data, length);strcat(msg.data, "\n\n");strcat(msg.data, response);printf("%s\n", msg.data);int r = send(msg.clientSocket, msg.data, 10000, 0);if (r == SOCKET_ERROR) {printf("send failed\n");*msg.isActive = false;return;}printf("send success\n");*msg.isActive = false;return;}else {std::cout << "str=" << str << " " << "paw=" << passwd << std::endl;char response[200];strcpy(response, "<html><body>登录失败</body></html>\n");int len = strlen(response);char length[20];sprintf(length, "%d", len);strcpy(msg.data, "HTTP/1.1 200 OK\n");strcat(msg.data, "Content-Type: text/html;charset=gb2312\nContent-Length: ");strcat(msg.data, length);strcat(msg.data, "\n\n");strcat(msg.data, response);printf("%s\n", msg.data);int r = send(msg.clientSocket, msg.data, 10000, 0);if (r == SOCKET_ERROR) {printf("send failed\n");*msg.isActive = false;return;}printf("send success\n");*msg.isActive = false;return;}pass_flag = false;}else if (str == "login") {login_flag = true;}else if (str == "pass") {pass_flag = true;}if (j == data.size())break;str = "";}else {str = str + msg.data[j];}}*msg.isActive = false;return;}else if (type=="GET" && data != "") {memset(msg.data, 0, sizeof(msg.data));if (data.substr(0, 5) == "/net/") {std::string str = "";std::string str1 = "";std::string passwd;std::string name;std::string path;bool txt_flag = false;for (int i = 5; i < data.size(); i++) {if (data[i] == '.') {flag = true;}else if (flag) {str = str + data[i];}}if (str == "") {*msg.isActive = false;return;}std::cout <<"str="<< str << ","<<std::endl;if (str == "txt") {path = "catalog/txt/" + data.substr(5);}else if (str == "html") {std::cout << "yes" << std::endl;path = "catalog/html/" + data.substr(5);std::cout << "path=" << path << std::endl;}std::cout << "str=" << str << std::endl;sendMessage(path, msg);}else if (data.substr(0, 5) == "/img/") {int total_size;int s;std::string path = "catalog/img/" + data.substr(5);sendMessage(path, msg);}}closesocket(msg.clientSocket);*msg.isActive = false;}void listenForClose(close_message msg){std::string str;while (1) {std::cin >> str;if (str == "quit") {while (1) {bool flag = true;for (int i = 0; i < ftpServer::MAX; i++) {if (msg.isActive[i]) {flag = false;break;}}if (flag) {closesocket(msg.serverSocket);exit(0);}}}else {printf("syntex error!\n");}}}bool httpServer::start(){int on = 1;memset(isActive, false, sizeof(isActive));close_message msg(isActive, serverSocket);th = new std::thread(listenForClose, msg);//初始化服务器  memset(&serverChannel, 0, sizeof(serverChannel));serverChannel.sin_family = AF_INET;serverChannel.sin_addr.s_addr = htonl(INADDR_ANY);serverChannel.sin_port = htons(SERVER_PORT);//创建套接字  serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (serverSocket < 0) {printf("cannot create socket\n");return false;}else printf("successfully create socket\n");setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR,(char*)&on, sizeof(on));//绑定  int b = bind(serverSocket, (sockaddr*)&serverChannel,sizeof(serverChannel));if (b < 0) {printf("bind error\n");return false;}else printf("successfully bind\n");//监听  int l = listen(serverSocket, 1);if (l < 0) {printf("listen failed\n");return false;}else printf("successfully listen\n");int len = sizeof(serverChannel);//服务器等待连接  while (1) {printf("waiting for connection...\n");//接受一个连接  clientSocket = accept(serverSocket, (sockaddr*)&serverChannel, &len);if (clientSocket < 0) {printf("accept failed\n");}else {printf("successfully connect\n");memset(buffer, 0, sizeof(buffer));int ret;ret = recv(clientSocket, buffer, BUFFER_SIZE, 0);if (ret == SOCKET_ERROR) {printf("sorry receive failed\n");}else if (ret == 0) {printf("the client socket is closed\n");}else {printf("successfully receive\n");for (int i = 0; i < MAX; i++) {if (!isActive[i]) {isActive[i] = true;message msg(buffer, &isActive[i], clientSocket, i);t[i] = new std::thread(handleMessage, msg);break;}}}}}}

main.cpp

#include"httpServer.h"#pragma(lib,"ws2_32.lib")int main(){httpServer f;f.start();system("pause");}


0 0
原创粉丝点击