一个仅能处理get请求的webserver

#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>

#define BUFF_SIZE 1024

using namespace std;

string document_root;
pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
//pthread_cond_t emp;
set<int> connections;//连接池
int timeout = 20;

string status_200 = "200 OK";
string status_400 = "400 Bad Request";
string status_403 = "403 Forbidden";
string status_404 = "404 Not Found";
string content_html = "text/html";
string content_text = "text/plain";
string content_jpeg = "image/jpeg";
string content_gif = "image/gif";
string http = "HTTP/1.1 ";
string content_type = "Content-Type: ";
string content_date = "Date: ";
string content_length = "Content-Length: ";

string generate_response(string resp_status, string resp_type_value, int length) {
    string response;
    char buf[1000];
    time_t now = time(0);
    struct tm tm = *gmtime(&now);
    strftime(buf, sizeof buf, "%a, %d %b %Y %H:%M:%S %Z", &tm);
    string date(buf);
    response.append(http);
    response.append(resp_status);
    response.append("\r\n");
    response.append(content_type);
    response.append(resp_type_value);
    response.append("\r\n");
    response.append(content_length);
    response.append(to_string(length+2));
    response.append("\r\n");
    response.append(content_date);
    response.append(date);
    response.append("\r\n");
    response.append("\r\n");
    cout << "Header: " << response << endl;
    memset(buf, 0, sizeof(buf));
    return response;
}

void *process_packet(void *socket){
    int clientsock = *((int *)socket);
    char buff[BUFF_SIZE];
    stringstream ss,ext;
    string request_type, file, file_path;
    char *data;

    //读取来自客户端的socket
    if(read(clientsock, buff, 1000)<0){
        cout << "Error in reading client socket" << endl;
        exit(0);
    }

    string content(buff);
    ss<< content;
    ss >> request_type;
    ss >> file;
    cout << "Request type: " << request_type << endl;//请求类型
	cout << "File: " << file << endl;//请求内容

    string token;
    ext << file;

    while (getline(ext, token, '.'));
    ss.str(string());
    ss.clear();
    ext.str(string());
    ext.clear();

    if(file.compare("/")==0){
        file.append("index.html");// 默认网页
        token = "html";
    }

    file_path = document_root;
    file_path.append(file);

    cout << "File path is : " << file_path << endl;

    string temp;
    int exists = access(file_path.c_str(), F_OK);
    int permission = access(file_path.c_str(),R_OK);

    char* image;
    streampos size;
    struct stat st;
    stat(file_path.c_str(),&st);
    if(exists !=-1&&(S_ISDIR(st.st_mode)==1)){ // 是文件夹
        cout << "** Bad Request **" << endl;
		temp = generate_response(status_400, content_html, 0);//生成响应
		send (clientsock, temp.data(), temp.length(), 0);// 发回给客户端
    }else if(exists != -1&& permission !=-1){
        pthread_mutex_lock(&lock1);
        if(token.compare("txt")==0){ //目标文件类型为txt
            cout << "Text file to be opened" << endl;
			ifstream fd(file_path, ios::in|ios::ate);
			if(fd.is_open()) {
				size = fd.tellg();
				data = new char [size];
				fd.seekg(0, ios::beg);
				fd.read(data, size);
				fd.close();

				temp = generate_response(status_200, content_text, strlen(data)-2);
				temp.append(data);

				send (clientsock, temp.data(), temp.length(), 0);

			} else {
				cout << "Cannot open file" << endl;
			}
        }
        else{
            ifstream fd(file_path, ios::in|ios::binary|ios::ate);
			if(fd.is_open()) {
				size = fd.tellg();
				data = new char [size];
				fd.seekg(0, ios::beg);
				fd.read(data, size);
				fd.close();

				if(token.compare("html") == 0) { // html 类型,jpeg类型,gif类型
					temp = generate_response(status_200, content_html, (int)size);
				} else if (token.compare("jpeg") == 0) {
					temp = generate_response(status_200, content_jpeg, (int)size);
				} else if (token.compare("gif") == 0) {
					temp = generate_response(status_200, content_gif, (int)size);
				}

				//Open file and read contents into buffer
				send (clientsock, temp.data(), temp.length(), 0);
				send(clientsock, data, size, 0);
			} else {
				cout << "Cannot open file" << endl;
			}
        }
        pthread_mutex_unlock(&lock1);

    }else if(permission == -1 && exists != -1) {
        // 无访问权限
		cout << "Permission Denied!" << endl;
		temp = generate_response(status_403, content_html, 0);
		send (clientsock, temp.data(), temp.length(), 0);

	} else {
        // 所请求文件不存在
		cout << "File not found!!!!!!" << endl;
		temp = generate_response(status_404, content_html, 0);
		send (clientsock, temp.data(), temp.length(), 0);

	}
    cout << "Exit thread" << endl;
    sleep(timeout);// 控制处理频率
    cout << "Removing connection " << clientsock << endl;
    connections.erase(clientsock);
    close(clientsock);
    pthread_exit(NULL);
}

//./server -document-root /home/jc/Downloads/GET-method-Webserver- -port 8003
int main(int argc, char* argv[]){

    int sockfd, clientsock;
    struct sockaddr_in serv_addr, clientaddr;
    socklen_t addr_size, clientaddr_len;


    // 输入参数
    document_root = argv[2]; //根目录
    int port = stoi(argv[4]); // 端口号

    sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建socket

    bzero((char *)&serv_addr, sizeof(serv_addr));

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(port);
    addr_size = sizeof(serv_addr);

    bind(sockfd, (struct sockaddr*)&serv_addr, addr_size);// 绑定sockket
    if(listen(sockfd, 5)<0) {
        cout << "Error in listening at socket!" << endl;
        exit(0);
    } // 监听socket

    pthread_t tid;//线程id

    while (1)
    {
        if((clientsock = accept(sockfd, (sockaddr*)&clientaddr,(socklen_t*)&clientaddr_len))<0){
            cout << "Error in accepting new connection!" << endl;
            exit(0);
        }
        connections.insert(clientsock);
        if(pthread_create(&tid,nullptr,process_packet,&clientsock)!=0){
            cout << "Failed to create new thread!" << endl;
        }

        pthread_detach(tid);//结束后释放资源

        if(timeout > 5)
			timeout -= connections.size();	
		else
			timeout = 20;

		cout << "Timeout " << timeout << endl;
    }
    return 0;
}

来源:https://github.com/apurwaj2/GET-method-Webserver-

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页