注:需建立在当前目录下的文件夹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");
}