#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;
}


相关推荐
05-19
2376
