当前位置: 首页 > news >正文

响应式网站好么wordpress孤单链接设置

响应式网站好么,wordpress孤单链接设置,北京商场关闭通知,重庆商城网站建设【网络编程】之TCP实现客户端远程控制服务器端及断线重连 TCP网络通信实现客户端简单远程控制主机基本功能演示通信过程代码实现服务器模块执行命令模块popen系列函数 客户端模块服务器主程序 windows作为客户端与服务器通信#pragma comment介绍 客户端使用状态机断线重连代码实… 【网络编程】之TCP实现客户端远程控制服务器端及断线重连 TCP网络通信实现客户端简单远程控制主机基本功能演示通信过程代码实现服务器模块执行命令模块popen系列函数 客户端模块服务器主程序 windows作为客户端与服务器通信#pragma comment介绍 客户端使用状态机断线重连代码实现运行结果 TCP网络通信实现客户端简单远程控制主机 基本功能演示 客户端与服务器端连接后可以通过Linux中的指令来控制它 但是为了防止客户端恶意破坏服务器我们必须创建一个配置文件只有在这个配置文件里的命令客户端才能执行。 通信过程 服务器端创建监听套接字监听客户端等待客户端连接。客户端发起连接请求。连接成功开始通信。客户端发送命令。服务器端接收到命令并创建一个新线程线程在线程调用的函数中设置为分离状态主线程不需要对子线程等待。新线程执行一系列函数后给客户端返回执行结果。 代码实现 服务器模块 TcpServer.hpp #pragma once #includeunistd.h #includesys/socket.h #includearpa/inet.h #includenetinet/in.h #includesys/types.h #includecstdio #includecstdlib #includeLog.hpp #includefunctional #includeThreadPool.hpp #includeInetAddr.hpp// 定义错误码 enum {SOCKETERROR 1, // 套接字创建失败BINDERROR, // 套接字绑定失败USAGEERROR // 用法错误 };// 定义服务函数的类型别名 using funcservice functionvoid(int sockfd, InetAddr addr);// 用于多线程任务的数据结构 struct Threaddata {int _sockfd; // 客户端连接的套接字InetAddr _addr; // 客户端的地址信息funcservice _exec; // 执行的服务函数Threaddata(int sockfd, InetAddr addr, funcservice exec): _sockfd(sockfd), _addr(addr), _exec(exec){} };// 定义业务逻辑函数类型别名 using funcexec functionstring(const string);// 定义 TcpServer 类 class TcpServer { private:int _listensock; // 监听套接字uint16_t _port; // 监听端口号bool _is_running; // 服务器运行状态funcexec _exec; // 业务逻辑处理函数public:// 构造函数初始化成员变量TcpServer(uint16_t port, funcexec exec): _listensock(-1), _port(port), _is_running(false), _exec(exec){}// 初始化服务器包括创建套接字、绑定地址和监听void InitServer(){_listensock socket(AF_INET, SOCK_STREAM, 0); // 创建 TCP 套接字if (_listensock -1){LOG(FATAL, socket error);exit(1); // 套接字创建失败退出}LOG(INFO, socket success);struct sockaddr_in addr;addr.sin_family AF_INET; // 使用 IPv4addr.sin_port htons(_port); // 设置端口号网络字节序addr.sin_addr.s_addr INADDR_ANY; // 监听本机所有网卡// 绑定地址if (bind(_listensock, (struct sockaddr*)addr, sizeof(addr)) -1){LOG(FATAL, bind error);exit(1); // 绑定失败退出}LOG(INFO, bind success);// 开始监听最大连接数为 5if (listen(_listensock, 5) -1){LOG(FATAL, listen error);exit(1); // 监听失败退出}}// 服务函数处理客户端请求void Service(int sockfd, InetAddr addr){LOG(INFO, new connect: %s:%d, inet_ntoa(addr.addr().sin_addr), ntohs(addr.addr().sin_port));while (_is_running){char buffer[1024]; // 接收缓冲区memset(buffer, 0, sizeof(buffer)); // 清空缓冲区int n recv(sockfd, buffer, sizeof(buffer), 0); // 接收数据string sender [ addr.ip() : to_string(addr.port()) ]#; // 记录客户端信息if (n -1){perror(recv);break;}else if (n 0){LOG(INFO, %sclient close, sender.c_str());break; // 客户端断开连接}else{buffer[n] 0; // 确保字符串以 \0 结束LOG(INFO, %s%s, sender.c_str(), buffer);// 执行业务逻辑函数string result _exec(buffer);// 返回处理结果给客户端string echoserver [echo server]#\n result;send(sockfd, echoserver.c_str(), echoserver.size(), 0);}}close(sockfd); // 关闭客户端连接}// 线程入口函数static void* ThreadRun(void* arg){pthread_detach(pthread_self()); // 设置线程分离防止资源泄漏Threaddata* data (Threaddata*)arg; // 获取任务数据data-_exec(data-_sockfd, data-_addr); // 执行服务函数delete data; // 释放任务数据return nullptr;}// 主循环接受客户端连接并分配任务void Loop(){_is_running true;while (_is_running){struct sockaddr_in peer; // 客户端地址socklen_t len sizeof(peer);int sockfd accept(_listensock, (struct sockaddr*)peer, len); // 接受连接if (sockfd -1){perror(accept);break;}InetAddr addr(peer); // 将客户端地址封装为 InetAddr 对象// 多线程版本Threaddata* data new Threaddata(sockfd, addr, std::bind(TcpServer::Service, this, placeholders::_1, placeholders::_2));pthread_t tid;pthread_create(tid, nullptr, ThreadRun, data); // 创建线程处理任务}_is_running false;}// 析构函数清理资源~TcpServer(){if (_listensock ! -1){close(_listensock); // 关闭监听套接字}} };执行命令的函数在外面传入类中当新线程接收数据后回调这个函数处理任务创建子进程处理执行命令并返回数据。 执行命令模块 #pragma once #includestring #includeset #includefstream #includeiostream #includeLog.hpp using namespace std;const static string seq ; const static string commandpath ./command.txt;class ExecuteCommand { private:setstring _CommandSet;//安全命令集合string _cond_path;//命令的路径 private:void LoadCommandSet()//加载安全命令集合{ifstream infile(commandpath, ios::in);//打开文件以读取的方式if(!infile.is_open())//判断文件是否打开成功{LOG(FATAL, open command.txt failed); //打开文件失败return;}string line;while(getline(infile, line))//读取文件中的安全命令{_CommandSet.insert(line);//插入到安全命令集合中}infile.close();//关闭文件}bool IsSecure(const string Command)//判断是否是安全命令{if(Command.empty())//判断命令是否为空{return false;}//先把核心命令提取出来不要后面的选项int pos Command.find(seq);//找到空格的位置string core Command.substr(0, pos);//提取核心命令//判断是否在安全命令集合中if(_CommandSet.find(core) ! _CommandSet.end())//在安全命令集合中{return true;}return false;//不在安全命令集合中} public:ExecuteCommand(const string path commandpath):_cond_path(path){LoadCommandSet();//加载安全命令集合}string Execute(const string Command){//1.先fork pipe//2.再exec 执行命令//3. 执行命令前 dup2//这些都可以通过库函数popen来实现//(这个函数是一个标准库函数用于创建一个管道然后调用fork产生一个子进程然后调用exec执行一个命令) if(!IsSecure(Command))//判断是否是安全命令{LOG(WARNING, command is not secure);return command is not secure;}else//是安全的命令{FILE* fp popen(Command.c_str(), r);//执行命令if(fp nullptr)//判断是否执行成功{LOG(WARNING, command execute failed);return command execute failed;}string result;char output[1024] {0};//定义一个缓冲区while(fgets(output, sizeof(output)-1, fp) ! nullptr)//读取命令的输出{result output;}pclose(fp);//关闭文件return result;}}~ExecuteCommand(){} };需求1. 执行安全的命令 2.将命令执行的结果发送给客户端。实现: 执行命令不能在子线程中执行命令因为子线程还要接收来自某个客户端的数据所有应该子线程创建一个子进程调用exec系列的函数执行命令。返回数据进程之间具有独立性我们选择使用匿名管道进行进程间通信。安全的命令可以通过创建一个配置文件然后创建命令对象时将配置文件加载进集合文件IO慢如果命令前缀在集合中就执行反之直接返回提示信息。 上述两个步骤都不需要我们自己去实现C语言库中提供了一个这样的函数可以帮我们完成上述功能我们来介绍这个函数 popen系列函数 FILE *popen(const char *command, const char *type)函数功能popen 是一个 C 库函数提供了一种简单的方式来创建一个管道pipe并启动一个子进程以执行外部命令。popen 允许父进程与子进程之间进行单向通信。 参数 const char *command你需要执行的命令及其选项例如 ls -lconst char *type r: 打开管道用于读取子进程的标准输出。 w: 打开管道用于写入子进程的标准输入。 返回值 成功返回一个指向管道文件的 FILE 指针。 失败返回 NULL。 头文件stdio.h int pclose(FILE *stream);功能 关闭管道文件。回收子进程防止它变成僵尸进程。 参数 FILE *stream由 popen 返回的指向管道的 FILE 指针。 返回值 成功: 返回子进程的退出状态以 waitpid 的方式返回可以通过 WEXITSTATUS 宏提取退出码。 失败: 返回 -1并设置 errno。 头文件stdio.h 客户端模块 和echo功能中的客户端模块基本一致。 #include iostream #include string #include unistd.h #includesys/socket.h #includearpa/inet.h #includenetinet/in.h #includestring.husing namespace std;void Usage(char* s) {cout Usage:\n\t s serverip serverport endl;exit(1); }int main(int argc,char* argv[]) {if(argc ! 3){Usage(argv[0]);return 1;}string ip argv[1];uint16_t port stoi(argv[2]);int sockfd socket(AF_INET,SOCK_STREAM,0);//创建套接字if(sockfd -1){perror(socket creat error);return 1;}//客户端需要bind,但是不需要我们显示的bind//客户端也不需要listen监听请求是服务器程序的工作struct sockaddr_in addr;//服务器的地址信息addr.sin_family AF_INET;addr.sin_port htons(port);inet_pton(AF_INET,ip.c_str(),addr.sin_addr.s_addr);if(connect(sockfd,(struct sockaddr*)addr,sizeof(addr)) -1){perror(connect error);return 1;}while(true){string message;cout please input message:;getline(cin,message);//获取用户输入的信息,一行一行的获取send(sockfd,message.c_str(),message.size()1,0);char buffer[1024];memset(buffer,0,sizeof(buffer));int n recv(sockfd,buffer,sizeof(buffer),0);if(n -1){perror(recv error);break;}else if(n 0){cout server close endl;break;}else{buffer[n] 0;cout buffer;}}close(sockfd);return 0; }服务器主程序 服务器主程序将命令处理函数bind并传给服务器类的成员以供子线程调用该方法。 #includeTcpServer.hpp // 引入自定义的头文件用于创建并管理服务器 #includememory // 引入内存管理的头文件用于创建智能指针 #includeExecuteCommand.hpp // 引入自定义的头文件用于执行命令 #includefunctional // 引入函数式编程的头文件用于创建函数对象void Usage(char* s) {cout Usage:\n\t s serverport endl; // 打印程序的命令行使用格式提示用户输入端口号exit(USAGEERROR); }int main(int argc,char* argv[]) {// 判断命令行参数是否正确if(argc ! 2) // 程序需要接收一个参数端口号{Usage(argv[0]); // 如果参数不为2则调用Usage函数打印使用说明return 1; // 退出程序返回错误码1}// 将命令行参数转为端口号uint16_t类型这是服务器监听的端口号uint16_t port stoi(argv[1]); // 使用stoi将字符串转化为整数类型的端口号// 创建TcpServer对象并初始化unique_ptrTcpServer server make_uniqueTcpServer(port,std::bind(ExecuteCommand::Execute,ExecuteCommand() , placeholders::_1 )); // 使用从命令行获得的端口号创建TcpServer实例server-InitServer(); // 初始化服务器进行绑定等操作server-Loop(); // 启动服务器开始接收和处理客户端请求return 0; }windows作为客户端与服务器通信 我们修改一下客户端的echo代码即可windows中的网络库与Linux上的有一些差异在Udp通信的时候已经介绍过了 #include iostream #include winsock2.h #include ws2tcpip.h #include string.h #includestring #pragma comment(lib, ws2_32.lib) // 自动链接 Winsock 库using namespace std;const string ip 47.98.179.70; const uint16_t port 8080;int main() {// 初始化 Winsock 库WSADATA wsaData;if (WSAStartup(MAKEWORD(2, 2), wsaData) ! 0) // 以指定版本初始化{cerr WSAStartup failed endl;return 1;}// 创建套接字使用IPv4地址族和TCP协议SOCK_STREAM表示流式套接字int sockfd socket(AF_INET, SOCK_STREAM, 0); // 创建TCP套接字if (sockfd INVALID_SOCKET) // 如果创建套接字失败打印错误并返回{cerr Socket creation failed: WSAGetLastError() endl;WSACleanup();return 1;}// 设置服务器的地址信息struct sockaddr_in addr; // sockaddr_in结构体用于存储服务器的网络地址addr.sin_family AF_INET; // 使用IPv4地址族addr.sin_port htons(port); // 设置服务器的端口号htons将端口号转换为网络字节序inet_pton(AF_INET, ip.c_str(), addr.sin_addr.s_addr); // 将IP地址字符串转换为网络字节序的二进制格式// 连接到服务器if (connect(sockfd, (struct sockaddr*)addr, sizeof(addr)) SOCKET_ERROR) // 调用connect连接服务器{cerr Connect failed: WSAGetLastError() endl; // 如果连接失败输出错误信息closesocket(sockfd);WSACleanup();return 1;}// 客户端和服务器之间进行通信while (true){string message;cout Please input message: ; // 提示用户输入消息getline(cin, message); // 从标准输入获取一行字符串作为消息// 将输入的消息发送到服务器int bytesSent send(sockfd, message.c_str(), message.size() 1, 0); // 发送消息到服务器1用于包括消息结尾的\0if (bytesSent SOCKET_ERROR) // 如果发送失败{cerr Send failed: WSAGetLastError() endl;break;}// 接收服务器返回的消息char buffer[1024]; // 定义接收缓冲区大小为1024字节memset(buffer, 0, sizeof(buffer)); // 将缓冲区初始化为0int n recv(sockfd, buffer, sizeof(buffer), 0); // 从服务器接收数据if (n SOCKET_ERROR) // 如果接收数据失败{cerr Recv failed: WSAGetLastError() endl; // 输出错误信息break; // 跳出循环关闭连接}else if (n 0) // 如果服务器关闭了连接{cout Server closed the connection. endl; // 打印提示信息break; // 跳出循环结束通信}else // 数据接收成功{buffer[n] 0; // 确保接收到的数据是一个合法的C字符串添加终止符\0cout Server: buffer endl; // 输出服务器返回的消息}}// 关闭套接字结束与服务器的通信closesocket(sockfd); // Windows 关闭套接字时使用 closesocket()WSACleanup(); // 清理 Winsock 库return 0; // 程序正常结束 }运行结果 #pragma comment介绍 这是一条预处理指令是Microsoft Visual C 编译器MSVC的扩展指令它的功能和gcc/g中的-l选项类似可以告诉编译器要链接的库的名称。 MSVCMicrosoft Visual C是由微软开发的一款集成开发环境IDE和编译器工具套件用于开发基于 C、C 和 C/CLI 的应用程序。 客户端使用状态机断线重连 状态机是一种用于描述系统行为数学模型它的核心是状态它通过定义不同的状态让系统执行不同的操作且执行这些操作时得到的结果会更新状态。 代码实现 #includeiostream #include sys/socket.h #include arpa/inet.h #include unistd.h #includememory #includestring #includestring.h// 枚举类型定义退出码 enum Exitcode {USAGEERR 1, // 命令输入错误SOCKETERR, // 创建 socket 失败INET_PTONERR // 地址转换失败 };// 枚举类型定义连接状态 enum Status {NEW, // 新建连接的状态CONNECTED, // 已连接状态连接或重连成功DISCONNECTED, // 连接失败的状态CONNECTEDING, // 正在连接的状态CLOSED // 经历重连但是失败了 };// 常量定义 const int defaultsocketfd -1; // 默认 socket 文件描述符 const int maxreconnectcount 5; // 最大重连次数 const int defaultinterval 2; // 每次重连的时间间隔秒// Clientconnect 类封装与服务器的连接管理和通信 class Clientconnect { public:// 构造函数初始化连接信息包括 IP端口最大重连次数和重连间隔Clientconnect(int16_t port, std::string ip, int maxcount maxreconnectcount, int interval defaultinterval):_port(port), _ip(ip), _maxcount(maxcount), _interval(interval), _socketfd(defaultsocketfd), _status(Status::NEW){}// 连接服务器void Connect(){// 1. 创建 socket_socketfd socket(AF_INET, SOCK_STREAM, 0);if (_socketfd 0){std::cerr create socket failed std::endl;exit(Exitcode::SOCKETERR);}struct sockaddr_in addr;memset(addr, 0, sizeof(addr));addr.sin_family AF_INET;addr.sin_port htons(_port); // 设置端口if (inet_pton(AF_INET, _ip.c_str(), addr.sin_addr.s_addr) 0) // 地址转换{std::cerr inet_pton error std::endl;exit(Exitcode::INET_PTONERR);}// 尝试连接int n connect(_socketfd, (struct sockaddr*)addr, sizeof(addr));if (n 0){Close(); // 连接失败关闭文件描述符_status Status::DISCONNECTED; // 设置为连接失败状态return;}_status Status::CONNECTED; // 连接成功}// 尝试重连void Reconnect(){_status Status::CONNECTEDING; // 设置为正在连接状态int cnt 0;while (true){cnt;std::cout 正在重连中... 重连次数: cnt std::endl;Connect(); // 尝试重新连接// 如果连接成功跳出循环if (_status Status::CONNECTED){std::cout 重连成功! std::endl;break;}// 如果超过最大重连次数退出if (cnt _maxcount){_status Status::CLOSED; // 设置为关闭状态std::cout 已达最大重连次数... std::endl;break;}sleep(_interval); // 重连间隔}}// 基本的 I/O 处理void Process(){while (true){std::cout client#;std::string message hello server!!;int n send(_socketfd, message.c_str(), message.size(), 0); // 发送数据if (n 0){std::cerr send error std::endl;_status Status::CLOSED; // 发送失败关闭连接}if (n 0){char buffer[1024] {0};n recv(_socketfd, buffer, sizeof(buffer), 0); // 接收数据if (n 0){std::cerr recv error std::endl;Close();_status Status::DISCONNECTED; // 接收失败设置为断开连接break;}buffer[n] 0;std::cout server# buffer std::endl;}sleep(1);}}// 关闭连接void Close(){if (_socketfd 0){close(_socketfd); // 关闭 socket_status Status::CLOSED; // 设置为关闭状态_socketfd -1;}}// 获取当前连接的状态Status status(){return _status;}private:std::string _ip;uint16_t _port;int _socketfd;int _maxcount; // 最大重连次数int _interval; // 重连间隔Status _status; // 当前连接状态 };// 客户端类负责管理客户端连接的生命周期 class Client { public:// 构造函数Client(int16_t port, std::string ip): _connect(port, ip){}// 执行客户端操作void Excute(){while (true){switch (_connect.status()) // 根据状态执行不同的操作{case Status::NEW: // 初始状态尝试连接_connect.Connect();break;case Status::CONNECTED: // 已连接状态处理数据_connect.Process();break;case Status::DISCONNECTED: // 连接失败尝试重连_connect.Reconnect();break;case Status::CLOSED: // 已关闭退出_connect.Close();return;default:break;}}}~Client() {}private:Clientconnect _connect; // 客户端连接对象 };// 输出程序用法 void Usage(const std::string process) {std::cout process serverip serverport std::endl;exit(Exitcode::USAGEERR); }// 程序入口 int main(int argc, char* argv[]) {if (argc ! 3){Usage(argv[0]);}int16_t port std::stoi(argv[2]);std::string ip argv[1];std::unique_ptrClient client std::make_uniqueClient(port, ip);client-Excute();return 0; }状态说明 NEW初始状态处于这个状态的客户端还未尝试连接服务器。CONNECTED连接服务器成功处于这个状态的客户端即将开始IO通信。CONNECTING正在连接服务器的状态这个状态一般是瞬时状态发生在开始连接了但是还未连接成功。DISCONNECTED连接失败的状态处于这个状态的服务器将会开始重连逻辑。CLOSED客户端套接字关闭一般发生在重连失败后。 状态机执行过程 运行结果 我们编译客户端程序并在本地云服务器创建一个具有echo功能的服务器程序测试如下情况 服务器未运行客户端运行起来了。 连接肯定是失败的进入重连逻辑。 服务器运行起来后关闭服务器。 一开始连接是成功的服务器和客户端可以正常的通信。但是服务器不再运行后客户端又开始重连未达到重连次数时又运行起服务器就可以重连成功。否则重连失败。
http://www.dnsts.com.cn/news/199116.html

相关文章:

  • 英文网站建设600深圳石岩小学网站建设
  • 做网站十大公司哪家好营销软文案例
  • 网站推广邮箱怎么做为什么推荐企业做网站
  • 厦门网站建设有哪些公司wordpress博客怎么用
  • 鹤壁网站seo城乡互动联盟网站建设
  • 怎么做网站访问量5173游戏交易网站源码
  • 做网站有什么好处静态网页制作成品
  • 东营定制网站建设服务做网站设计好的公司
  • 怀化网站建设联系方式发布建设网站
  • 用r做简易的网站免认证域名
  • asp网站建设与设计wordpress要不要放网站地图
  • 电脑咋建网站云南省网站开发
  • 江西省大余县建设局网站建设部网站职业资格证查询
  • 网站根域名是什么免费网站建设多少钱
  • 一个网站怎么做软件企业网站建设指标
  • 大通证券手机版下载官方网站下载wordpress主页教程
  • 网站建设与维护的内容网站内容管理软件
  • 中山免费建站wordpress模板在哪购买
  • wordpress全站模板wordpress答题插件
  • 怎么建立自己网站视频域名服务器ip地址
  • 金华在线制作网站暂时关闭wordpress插件
  • 用ps做网站还是wd四川二级站seo整站优化排名
  • 网站建设部署与发布答案深圳上市公司排名
  • 知识付费网站开发网站做专题主题该怎么选
  • 商标查询网站建设wordpress广告赚钱
  • 学校建设网站的意义网站建设技术代码
  • 网站建设与维护简称seo优化工具的种类
  • 建设外国商城网站亚马逊欧洲站入口网址
  • 做电影网站 资源怎么存放卡片式主题wordpress
  • seo整站优化更能准确获得客户网站首页设计收费