学无先后,达者为师

网站首页 编程语言 正文

编写socket配置文件

作者:weixin_101 更新时间: 2023-07-08 编程语言

1. 读取文件类

  1. 头文件 config.h
#ifndef __CONFIG_H_
#define __CONFIG_H_

#include <map>
#include <iostream>
#include <string>
#include <fstream>
//定义配置文件注释符号
constexpr auto COMMENT_CHAR = '#';


using namespace std;
class Config_handle {
public:
	Config_handle();
	~Config_handle();

private:
	bool read_config_file(const string& filename, map<string, string>& m);

	//逐行读取处理
	bool analyse_line(const string& line, string& key, string& value);

	//去空格
	void trim_str(string& str);

	//是否空格或者tab键
	bool is_space_or_tab(char c);

	//配置文件路径
	const string config_file_path = "./conf/server.conf";

};
#endif //! __CONFIG_H_


  1. 源文件:config.cpp
#include "config.h"
#include "server.h"


Config_handle::~Config_handle()
{
}

Config_handle::Config_handle()
{
	map<string, string>maps;
	read_config_file(config_file_path, maps);
	map<string, string>::iterator iter;
//	for (itr = maps.begin(); itr != maps.end(); ++itr) {
//		cout << itr->first <<"="<< itr->second << endl;;
//	}

    //socket ip
	iter = maps.find("server_ip");
	string server_ip;
	if (iter != maps.end()) {
		server_ip = iter->second;
		//判断ip是否为合法ipv4
		if (inet_addr(server_ip.c_str()) == -1) {
			cout << "\e[0;31mserver_host error:\e[0m ipv4 syntax error" << endl;
			return;
		}
	}

	//socket 端口
	string port;
	iter = maps.find("port");
	if (iter != maps.end()) {
		port = iter->second;
		for (int i = 0; i < port.length(); i++) {
			if (!(isdigit(port[i]))) {
				cout << "\e[0;31mserver_port error:\e[0m port not support!" << endl;
				return;
			}
		}
		//判断端口是否为合法端口范围
		if (0 <(atoi(port.c_str())) && (atoi(port.c_str())) < 65535) {
			Tcp_server init_server = Tcp_server(server_ip.c_str(), port.c_str());
			//init_server.init_socket();
		}
		else {
			cout << "\e[0;31mserver port error:\e[0m value range 0-65535 " << endl;;
			return;
		}
	}
}


bool Config_handle::read_config_file(const string& filename, map<string, string>& m)
{
	m.clear();
	ifstream infile(filename.c_str());
	if (infile.is_open()) {
		string line_str, key, value;
		while (getline(infile, line_str)) {
			if (analyse_line(line_str,key,value)) {
				m[key] = value;
			}
		}
		//cout << "success" << endl;
		infile.close();
		return true;
	}
	//cout << "open file error: " << __FILE__ << " \nerror Function: " << __FUNCTION__ << "\nerror row: " << __LINE__ << endl\e[0;31m ;
	perror("\e[0;31mopen server.conf error:\e[0m");
	infile.close();
	return false;
}


bool Config_handle::analyse_line(const string& line_str, string& key, string& value)
{
	//是否为空
	if (line_str.empty())
		return false;
	int start_pos = 0, end_pos = line_str.size() - 1, pos;
	//是否存在注释号 '#' 
	pos = line_str.find(COMMENT_CHAR);
	if (pos != string::npos) {
		if (0 == pos) { //行的第一个字符就是注释字符
			return false;
		}
		//end_pos截止到‘#号,后面为注释’
		end_pos = pos - 1;
	}

	//预处理,删除注释部分
	string new_line = line_str.substr(start_pos, start_pos + 1 - end_pos); 
	pos = new_line.find('=');
	if (pos == string::npos)
		return false;   //没有 = 等号


	key = new_line.substr(0, pos);
	value = new_line.substr(pos + 1, end_pos + 1 - (pos + 1));
	
	trim_str(key);
	if (key.empty()) {
		return false;
	}
	trim_str(value);
	return true;
}


void Config_handle::trim_str(string& str)
{
	if (str.empty()) {
		return;
	}
	int i, start_pos, end_pos;
	for (i = 0; i < str.size(); ++i) {
		if (!is_space_or_tab(str[i])) {
			break;
		}
	}
	if (i == str.size()) { // 全部是空白字符串
		str = "";
		return;
	}
	start_pos = i;
	for (i = str.size() - 1; i >= 0; --i) {
		if (!is_space_or_tab(str[i])) {
			break;
		}
	}
	end_pos = i;
	str = str.substr(start_pos, end_pos - start_pos + 1);
}


bool Config_handle::is_space_or_tab(char c)
{
	if (' ' == c || '\t' == c)
		return true;
	return false;
}


2. 编写TCP socket

  1. 头文件server.h
#ifndef __SERVER_H_
#define __SERVER_H_

#include <iostream>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <cctype>
#include <cstring>
#include <unistd.h>
#include "config.h"

const int reject = -2;
const int fail = -1;
const int success = 0;


class Tcp_server {
public:
     Tcp_server(const char* ip, const char* port);
	 ~Tcp_server();
	 int  init_socket();
	 int server_accept();
 
private:
	const char* server_ip;
	const char* server_port;
    
	int recv_msg(int);
};

 
#endif


  1. 源文件: server.cpp
#include "server.h"

//侦听套接字
static int s_sock = -1;

Tcp_server::Tcp_server(const char* ip, const char* port) :
	server_ip(ip),
	server_port(port)
{
	int init_status = init_socket();
	//判断初始化成功---接收请求
	if (success == init_status) {
		perror("start...\e[0;32m");
		cout << "\e[0m" << endl;
		server_accept();
	}
}

Tcp_server::~Tcp_server()
{
}


int Tcp_server::init_socket()
{
	//创建套接字
	s_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (s_sock == fail) {
		perror("\e[0;31mcreate socket error!!!\e[0m") /*__TIME__ << __LINE__ << std::endl;*/;
		return fail;
	}
	//设置套接字
	int on = 1;
	int set_s = setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if (set_s == -1) {
		perror("setsockopt error\n");
		return fail;
	}

	//绑定端口号
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(atoi(server_port));
	if (string(server_ip) == "127.0.0.1") {
		addr.sin_addr.s_addr = inet_addr(server_ip) /*INADDR_ANY*/;
	}
	else {
		addr.sin_addr.s_addr = INADDR_ANY /*INADDR_ANY*/;
	}

	if (bind(s_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		perror("\e[0;31mbind error\e[0m");
		//std::cout << "bind() error "<< __LINE__ << std::endl;
		return fail;
	}

	//侦听套接字
	if (listen(s_sock, 1024) == -1) {
		std::cout << "Listen error " << __LINE__ << __FILE__ << std::endl;
		return fail;
	}
	return success;
}


int Tcp_server::server_accept() {
	//接收请求
	//接受客户机连接
	for (;;) {
		struct sockaddr_in addrcli = {};
		socklen_t addrlen = sizeof(addrcli);
		int conn = accept(s_sock, (struct sockaddr*)&addrcli, &addrlen);
		if (conn == -1) {
			perror("accept");
			return -1;
		}
		std::cout << "connectioned client status: " << inet_ntoa(addrcli.sin_addr) << " " << ntohs(addrcli.sin_port) << endl;
		string buf = "welcome to DJ BB!\n>";
		char username[10] = "username:";
		ssize_t send_msg = send(conn, buf.c_str(), buf.length(), 0);
		send_msg = send(conn, username, 10, 0);
		if (send_msg == -1) {
			perror("send:");
			return -1;
		}

		pid_t pid = fork();
		if (pid == -1) {
			perror("fork create error:");
			return -1;
		}
		else if (pid == 0) {
			if (close(s_sock) == -1) {
				perror("close s_sock error: ");
				return -1;
			}

			//进入fork处理接收信息
			int recv_status = recv_msg(conn);
			switch (recv_status) {
			case success:
				break;
			case fail:
				break;
			case reject:
				cout << "client IP reject: " << inet_ntoa(addrcli.sin_addr) << endl;
				//关闭连接
				if (close(conn) == -1) {
					perror("close client connection error:");
				}
				if (close(pid) == -1) {
					perror("close fork error:");
				}
				return reject;
			}

			//关闭连接
			if (close(conn) == -1) {
				perror("close client connection error:");
			}
			if (close(pid) == -1) {
				perror("close fork error:");
			}
			return success;
		}
	}
}

int Tcp_server::recv_msg(int conn)
{
	for (;;) {
		char username[1024] = { 0 };
		ssize_t recv_msg = recv(conn, username, sizeof(username), 0);
		if (recv_msg == -1) {
			perror("recv_msg error:");
			close(conn);
			return fail;
		}

		if (recv_msg == 0) {
			break;
		}
		cout << username << endl;

		if (username == "root") {
			char password[10] = "password:";
			cout << "equal" << endl;
			cout << username;
			memset(username, '\0', sizeof(username));
			ssize_t send_msg = send(conn, password, 10, 0);
			return success;
		}
		else {
			memset(username, '\0', sizeof(username));
			string reject_str = "Code:403, Connection closed by foreign host.";
			ssize_t send_msg = send(conn, reject_str.c_str(), reject_str.length(), 0);
			return reject;
		}
	}
}

原文链接:https://blog.csdn.net/weixin_41560737/article/details/126579179

  • 上一篇:没有了
  • 下一篇:没有了
栏目分类
最近更新