C++搭建简单的服务器

服务器代码

using namespace std;
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include<map>
#include <fstream>
#include<string>
#include <ctime>
#include<iostream>
using namespace std;

//最大传输大小
#define MAXSIZE 1024
#define SERVER_PORT 80
#define BACKLOG     10

//按行读取接收报文
string ReadLine(char recieve[], int &loc)
{
	int next_char;
	string data = "";
	while (true)
	{
		next_char = recieve[loc++];
		if (next_char == '\n')
		{
			break;
		}
		else if (next_char == '\r')
		{
			continue;
		}
		else if (next_char == '\0')
		{
			break;
		}
		data += next_char;
	}
	return data;
}

//处理HTTP请求类
class HttpRequestHandle {
public:
	//初始化
	HttpRequestHandle(unsigned char recieved[]) {
		memcpy(recieve, recieved, MAXSIZE);
		loc = 0;
		Http_method = "";
		Http_url = "";
	}
	//获得请求头
	void GetHeadInfo() {
		string line;
		string head = ReadLine(recieve, loc);//请求行
		//获得方法
		int loc_head = 0;
		while (head[loc_head] != ' ') {
			Http_method += head[loc_head];
			loc_head++;
		}
		loc_head++;
		while (head[loc_head] != ' ') {
			Http_url += head[loc_head];
			loc_head++;
		}
		while ((line = ReadLine(recieve, loc)) != "") {
			//分解报文头
			int seq_index = line.find_first_of(":");
			if (seq_index != -1) {
				string type = line.substr(0,seq_index);
				string value = line.substr(seq_index+1,line.size());
				HttpHeaders.insert(make_pair(type,value));
			}
			cout << line << endl;
		}
	}
	void GetHttpBody() {
		while (recieve[loc] != '\0') {
			body += recieve[loc];
			loc++;
		}
	}
	string GetMethod() {
		return Http_method;
	}
	string GetURL() {
		return Http_url;
	}
	string GetBody() {
		return body;
	}
private:
	char recieve[MAXSIZE];//接收字符
	string Http_method;//请求方式
	string Http_url;//URL地址
	string body;
	map<string, string> HttpHeaders;
	int loc;//读取位置
};

//处理方法类
class MyFunction {
public:
	MyFunction(string Http_method, string Http_url, string body) {
		this->body = body;
		this->Http_method = Http_method;
		this->Http_url = Http_url;
	}
	string Deal() {
		string deal_str = "";
		if (Http_method == "GET") {
			int id = chooseGet();
			switch (id) {
			case 0:
			    deal_str = index("测试.html");
			    break;
			case 1:
				deal_str = index("hello.html");
				break;
			default:
				break;
			}
		}
		else if (Http_method == "POST") {
            int id = choosePOST();
            cout<<"POST Body-------->"<<body<<endl;
			switch (id) {
			case 0:
			    deal_str = index("测试.html");
			    break;
			case 1:
				deal_str = index("hello.html");
				break;
			default:
				break;
			}
		}
		return deal_str;
	}

	//根据GET的URL选择方法
	int chooseGet() {
		if (Http_url == "/") {
            //如果为加载主页面
            return 0;
		}
		else if(Http_url == "/hello"){
		    //测试URL
		    return 1;
		}
		else {
			return -1;
		}
	}
	//根据POST的URL和Body选择方法
	int choosePOST() {
		if (Http_url == "/") {
            //如果为加载主页面
            return 0;
		}
		else if(Http_url == "/hello"){
		    //测试URL
		    return 1;
		}
		else {
			return -1;
		}
	}
	//方法1:测试用
	string test() {
		return "hello";
	}
	//获得HTML页面
	string index(string filename){
	    fstream fin;
	    fin.open(filename.c_str(), ios::in);
	    if(!fin){
            cout<<"文件不存在"<<endl;
            return "";
        }
        string v = "";
        string tmp;
        while (getline(fin, tmp)) {
            v += tmp;
        }
        fin.close();
        return v;
	}
private:
	string Http_method;//请求方式
	string Http_url;//URL地址
	string body;
};

class HttpResponseHandle {
public:
	HttpResponseHandle(string send) {
		this->send = send;
		Http_State = "200";//成功状态
		Http_phrase = "OK";
		Http_protocol_versionstring = "HTTP/1.1";
		HttpHeaders.insert(make_pair("Connection","keep-alive" ));
		HttpHeaders.insert(make_pair("Server","C++" ));
		HttpHeaders.insert(make_pair("Content-Type","text/html;charset=UTF-8"));
	}

	void SetSend() {
		string headerstr = "";
		headerstr = Http_protocol_versionstring + " " + Http_State + " " + Http_phrase + "\r\n";
		string Header_line = "";
		map<string, string>::reverse_iterator   iter;
		//HttpHeaders["Content-Length"] = ""+send.size();
		for (iter = HttpHeaders.rbegin(); iter != HttpHeaders.rend(); iter++) {
			Header_line += iter->first + ":" + iter->second + "\r\n";
		}
		headerstr += Header_line ;
		send = headerstr + "\r\n" + send+'\0';
        cout<<"send----->"<<send<<endl;
	}

	string GetSend() {
		return send;
	}

private:
	string Http_State;
	string Http_phrase;
	string Http_protocol_versionstring;
	string Content_Type;
	map<string, string> HttpHeaders;
	string send;
};

struct s_info {                     //定义一个结构体, 将地址结构跟cfd捆绑
    struct sockaddr_in cliaddr;
    int connfd;
};

void *do_work(void *arg){
    struct s_info *ts = (struct s_info*)arg;
    unsigned char ucRecvBuf[MAXSIZE];
    int iRecvLen = 0;
    while(1){
        iRecvLen = read(ts->connfd, ucRecvBuf, MAXSIZE);
        if(iRecvLen==0){
            printf("the client %d closed...\n", ts->connfd);
            break;
        }
        cout<<"Request:"<<ucRecvBuf<<endl;
		HttpRequestHandle httpreq(ucRecvBuf);
		httpreq.GetHeadInfo();
		httpreq.GetHttpBody();
		MyFunction function(httpreq.GetMethod(), httpreq.GetURL(), httpreq.GetBody());
		string response_str = function.Deal();
		HttpResponseHandle response(response_str);
		response.SetSend();
		string send_str = response.GetSend();
		cout<<"Response:"<<send_str<<endl;
		write(ts->connfd, send_str.c_str(), strlen(send_str.c_str()));
    }
    close(ts->connfd);
    printf("close socket\n");
    close(ts->connfd);
    return (void *)0;
}


int main()
{
	struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int listenfd, connfd;
    pthread_t tid;
    struct s_info ts[256];      //根据最大线程数创建结构体数组.
    int i = 0;

    listenfd = socket(AF_INET, SOCK_STREAM, 0);                     //创建一个socket, 得到lfd
    int option = 1;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
    bzero(&servaddr, sizeof(servaddr));                             //地址结构清零
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);                   //指定本地任意IP
    servaddr.sin_port = htons(SERVER_PORT);                           //指定端口号 8000

    if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))==-1) //绑定
    {
        printf("端口被占用\n");
    }

    listen(listenfd, 128);      //设置同一时刻链接服务器上限数

    printf("Accepting client connect ...\n");

    while (1) {
        cliaddr_len = sizeof(cliaddr);
        connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);   //阻塞监听客户端链接请求
        ts[i].cliaddr = cliaddr;
        ts[i].connfd = connfd;

        /* 达到线程最大数时,pthread_create出错处理, 增加服务器稳定性 */
        pthread_create(&tid, NULL, do_work, (void*)&ts[i]);
        pthread_detach(tid);                                                    //子线程分离,防止僵线程产生.
        i++;
    }

    return 0;
}

模拟请求
测试.html

<!DOCTYPE html>
<html>
<head>
	<title>测试HTTP请求</title>
</head>
<body>
    <p style="font-family:arial;font-size:30px;text-align:center">模拟HTTP请求</p><hr>
    <p style="font-family:arial;font-size:25px;text-align:center">
    	URL:<input type="text" name="port" id="url"><hr>
    </p>
    <p style="font-family:arial;font-size:25px;text-align:center">
    	Method:
    	<input type="radio" name="method" value="GET" checked>GET
    	<input type="radio" name="method" value="POST" >POST
    	<hr>
    </p>
    </p>
     <p style="font-family:arial;font-size:25px;text-align:center">
    	BODY:<br>
    	<textarea rows="10" cols="30" id="body">
    		json报文
    	</textarea>
    </p>
    <hr>
    <p style="font-family:arial;font-size:25px;text-align:center">
    	<input type="submit" value="提交" onclick="SendRequest()">
    	<input type="submit" value="清除">
    </p>
    

    <script>
        function SendRequest() {
        	var URL = document.getElementById("url").value ;
            var choose = document.getElementsByName("method");
            var Method = "";
            if(choose[0].checked){
            	Method = "GET";	
            }
            else if(choose[1].checked){
            	Method = "POST";	
            }
            else{
            	alert("请选择请求方式");
            	return;
            }
            var Body = document.getElementById("body").value;
            if(Method=="GET"){
            	var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        document.getElementById("body").value = xhttp.responseText;
                    }
                    else{
                    	document.getElementById("body").value = xhttp.responseText;
                    }
                };
                xhttp.open("GET", URL);
                xhttp.send();
            }
            else if(Method == "POST"){
                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function() {
                    if (this.readyState == 4 && this.status == 200) {
                        document.getElementById("body").value = xhttp.responseText;
                    }
                    else{
                    	document.getElementById("body").value = xhttp.responseText;
                    }
                };
                xhttp.open("POST", URL);
                xhttp.send("SDASDASDDDDDDDDDDDDDDFJDHJD");
            }
            else{

            }
        }
    </script>
 </body>
</html>

测试网页
hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>
    你好
  </h1>
</body>
</html>
  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的TCP服务器和客户端的实现示例: ```c // 服务器端代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main(int argc, char const *argv[]) { int sockfd, newsockfd, valread; struct sockaddr_in serv_addr, cli_addr; socklen_t cli_addr_len; char buffer[BUFFER_SIZE] = {0}; // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(EXIT_FAILURE); } // 设置服务器地址 memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(PORT); // 绑定套接字到指定端口 if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { perror("bind"); exit(EXIT_FAILURE); } // 监听套接字 if (listen(sockfd, 5) == -1) { perror("listen"); exit(EXIT_FAILURE); } printf("Server listening on port %d...\n", PORT); // 接收连接请求 cli_addr_len = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &cli_addr_len); if (newsockfd == -1) { perror("accept"); exit(EXIT_FAILURE); } printf("Client connected!\n"); // 读取客户端发送的数据 valread = read(newsockfd, buffer, BUFFER_SIZE); printf("Received message from client: %s\n", buffer); // 发送响应数据给客户端 const char *response = "Hello, client!"; if (send(newsockfd, response, strlen(response), 0) == -1) { perror("send"); exit(EXIT_FAILURE); } printf("Response sent to client!\n"); // 关闭套接字 close(newsockfd); close(sockfd); return 0; } ``` ```c // 客户端代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define PORT 8080 #define BUFFER_SIZE 1024 int main(int argc, char const *argv[]) { int sockfd, valread; struct sockaddr_in serv_addr; char buffer[BUFFER_SIZE] = {0}; // 创建套接字 sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(EXIT_FAILURE); } // 设置服务器地址 memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) == -1) { perror("inet_pton"); exit(EXIT_FAILURE); } // 连接服务器 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1) { perror("connect"); exit(EXIT_FAILURE); } printf("Connected to server!\n"); // 发送数据到服务器 const char *message = "Hello, server!"; if (send(sockfd, message, strlen(message), 0) == -1) { perror("send"); exit(EXIT_FAILURE); } printf("Message sent to server!\n"); // 读取服务器响应数据 valread = read(sockfd, buffer, BUFFER_SIZE); printf("Received message from server: %s\n", buffer); // 关闭套接字 close(sockfd); return 0; } ``` 以上代码演示了客户端向服务器发送一条消息,服务器接收到消息后回复一条消息。可以根据实际需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Who_Am_I.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值