企业做网站需要什么资料爱战网关键词挖掘
news/
2025/10/1 16:14:06/
文章来源:
企业做网站需要什么资料,爱战网关键词挖掘,360官网首页入口,商务网站的基本情况文章目录 服务端通过传入命令处理实现远程命令执行使用Windows编辑UDP客户端实现Windows远程控制Linux接收套接字的其他信息UDP套接字简单群聊服务端UDP套接字简单群聊客户端运行测试及分离输入输出 参考代码 服务端通过传入命令处理实现远程命令执行 『 Linux 』利用UDP套接字… 文章目录 服务端通过传入命令处理实现远程命令执行使用Windows编辑UDP客户端实现Windows远程控制Linux接收套接字的其他信息UDP套接字简单群聊服务端UDP套接字简单群聊客户端运行测试及分离输入输出 参考代码 服务端通过传入命令处理实现远程命令执行 『 Linux 』利用UDP套接字简单进行网络通信 中实现了利用UDP套接字实现简单的网络通信(参考代码[gitee - udp process]); 具体思路是实现利用UDP套接字实现一个客户端和一个服务端,客户端向服务端发送数据,服务端进行数据的拼接并返回拼接后的数据,或者是传入一个回调函数,服务端通过调用回调函数调用popen接口创建子进程执行命令;
std::string HandlerCommand(const std::string cmd) {// 打开管道执行命令FILE* fp popen(cmd.c_str(), r);if (!fp) {perror(popen);return error;}std::string ret;char buffer[4096];// 循环读取命令输出while (true) {char* res fgets(buffer, sizeof(buffer), fp);if (res nullptr) break; // 到达文件末尾或出错ret std::string(buffer); // 将命令输出追加到返回字符串中}// 关闭管道并获取命令执行的返回值int status pclose(fp);if (status -1) {perror(pclose);return error;}// 返回命令执行结果return ret;
}可以创建一个子函数使用string::find判断命令中是否存在不安全的操作,如rm,sudo等;
bool isSave(const std::string cmd) {std::vectorstd::string unsaves {rm, while, sudo,mv, cp, yum};int pos 0;for (auto world : unsaves) {pos cmd.find(world);if (pos ! std::string::npos) {return false;}}return true;
}std::string HandlerCommand(const std::string cmd) {// 打开管道执行命令if (!isSave(cmd)) {return the cmd unsave;}FILE* fp popen(cmd.c_str(), r);if (!fp) {perror(popen);return error;}std::string ret;char buffer[4096];// 循环读取命令输出while (true) {char* res fgets(buffer, sizeof(buffer), fp);if (res nullptr) break; // 到达文件末尾或出错ret std::string(buffer); // 将命令输出追加到返回字符串中}// 关闭管道并获取命令执行的返回值int status pclose(fp);if (status -1) {perror(pclose);return error;}// 返回命令执行结果return ret;
}测试结果为: 这里的服务端地址在测试时可以使用环回地址,即127.0.0.1或127.0.0.0; 环回地址 环回地址是一个特殊的IP地址,用于主机自己与自己通信,不与任何物理网络接口相关联; 通常用于进行CS测试,即客户端与服务端之间的测试; 在IPv4中的环回地址通常为127.0.0.0/8网段; IPv6中的环回地址通常为::1; 主机名local host通常会被映射到环回地址,环回地址通常是安全的,因为数据不会离开主机; 本质上Xshell等软件就是通过类似的原理实现本地与远端服务器进行网络通信(所用协议不同); 使用Windows编辑UDP客户端实现Windows远程控制Linux 服务端已经实现,此处不考虑服务端;
#define _CRT_SECURE_NO_WARNINGS 1 // 使用VS编译器预防警告#include stdio.h
#include tchar.h
#include iostream
#include WinSock2.h
#include Windows.h
#include WS2tcpip.h
#include string#pragma comment(lib, ws2_32.lib)enum ERR {SOCKETERR 1,INETPTONERR
};// 封装客户端
class UdpClient {
public:UdpClient(const std::stringip,UINT16 port):sockfd_(0),ip_(ip),port_(port),len_(0) // 初始化客户端的值{memset(local_, 0, sizeof(local_)); // 初始化struct stockaddr结构体为0if (WSAStartup(MAKEWORD(2, 2), wsd_)) {} // 取消警告 }void Run() {/*进行套接字的运行与数据的发送接收及管理*/Init(); // 进行套接字的初始化std::string message; // 用于存储需要发送给服务端的字符串数据char buffer[1024] { 0 }; // 用于存储服务端返回给客户端的内容while (true) {std::cout Please Enter ; // 消息提示符std::getline(std::cin,message); // 从键盘中接收需要发送给服务端的数据int sd sendto(sockfd_, message.c_str(), message.size(), 0, (sockaddr*)local_, len_); // 调用sendto发送给服务端if (sd 0) {std::cout sendto err std::endl;}struct sockaddr_in tmp; // 创建 sockaddr_in 作为服务端发来数据包的其他信息(IP,端口等)memset(tmp,0, sizeof(tmp)); // 初始化结构体socklen_t len sizeof(tmp); // 作为输出型参数接收服务端发来数据包的大小SSIZE_T n recvfrom(sockfd_, buffer, 1023, 0, (struct sockaddr*)tmp, len); // 使用 recvfrom 接收来自服务端的信息if (n 0) {buffer[n] 0;std::cout buffer std::endl; // 当做字符串进行打印}}}~UdpClient() {WSACleanup();closesocket(sockfd_); // 关闭套接字文件描述符}
protected:void Init() {/*进行套接字的初始化工作*/// 设置 sockaddr_in 结构体local_.sin_family AF_INET; // 设置网络传输为IPv4协议local_.sin_port htons(port_); // 设置端口号 - 需要发送给服务端需要转网络字节序if (inet_pton(AF_INET, ip_.c_str(), local_.sin_addr) ! 1) {std::cerr Init - sin_addr erro std::endl;exit(INETPTONERR);}len_ sizeof(local_); // 计算 sockaddr_in 结构体大小// 创建套接字sockfd_ socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP套接字并存储套接字文件描述符if (sockfd_ 0) {std::cerr soket fail std::endl;exit(ERR::SOCKETERR);}}private:SOCKET sockfd_;std::string ip_;UINT16 port_;struct sockaddr_in local_;WSADATA wsd_;socklen_t len_;
};int main() {std::string ip; UINT16 port;// 打印提示符信息并输入IP与端口std::cout Please Enter your IP ;std::cin ip;std::cout Please Enter your port ;std::cin port;// 实例化一个客户端实例并传入IP与端口UdpClient client(ip, port);// 调用客户端的运行(运行中自动进行初始化)client.Run();return 0;
}这里封装了一个Windows版本的Client客户端; 头文件和预处理指令 包含了必要的头文件,如WinSock2.h用于网络编程; #define _CRT_SECURE_NO_WARNINGS 1用于禁用某些Visual Studio的安全警告; #pragma comment(lib, ws2_32.lib) 链接 Windows Socket 网络库; 错误枚举 enum ERR {SOCKETERR 1,INETPTONERR
};定义了两种错误类型,用于错误处理; UdpClient类 主要的客户端类,封装了UDP客户端的功能; 构造函数 UdpClient(const std::stringip,UINT16 port):sockfd_(0),ip_(ip),port_(port),len_(0)用于初始化客户端,设置IP地址和端口号,调用了WSAStartup初始化Winsock; Run方法 void Run()客户端的主要运行方法,首先调用Init函数进行初始化,然后进入一个无限循环,不断从用户获取输入并发送到服务器,并接收服务器的响应; 析构函数 ~UdpClient()清理资源,关闭套接字文件描述符,调用WSACleanup; Init函数 void Init()初始化套接字和地址结构; 设置sockadddr_in结构并创建UDP套接字; 客户端不需要显式bind,当调用sendto将数据发送给服务端时将自动生成一个port端口bind当前IP; 私有成员 private:SOCKET sockfd_; // 套接字文件描述符std::string ip_; // IPUINT16 port_; // 端口号struct sockaddr_in local_; // sockaddr_in 结构体WSADATA wsd_; // WSADATA 变量socklen_t len_; // sockaddr_in 结构体的大小套接字描述符,IP地址,端口号,地址族结构体等; main函数 从用户获取IP地址和端口号; 创建UdpClient实例; 调用client.Run()开始运行客户端; 主要流程为用户输入服务器IP和端口并创建UdpClient对象; 调用Run函数: 初始化套接字(调用Init); 进入循环: 获取用户输入 发送到服务器 接收服务器响应并显示 由于协议分层,Windows与Linux不同平台可以使用同一套协议簇进行网络通信; 因为即使是不同平台下Socket API网络接口是一致的; 接收套接字的其他信息 当服务端接收到客户端所发的信息时这个数据包中存放的除了数据以外还包含着客户端的基本信息,如IP地址和端口号;
/* UdpServer.hpp */
#include log.hpp // 日志头文件#define BUF_SIZE 1024// 定义函数类型别名
using Comfunc_t std::functionstd::string(const std::string );
using Echofunc_t std::functionstd::string(const std::string ,const std::string , uint16_t);Log log_;// 错误码枚举
enum { SOCK_CREATE_FAIL 1, SOCK_BIND_FAIL };class UdpServer {public:// 构造函数UdpServer(const uint16_t port defaultport): sockfd_(0), port_(port), isrunning_(false) {}~UdpServer() {}// 初始化服务器void Init() {// 创建 UDP socketsockfd_ socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ 0) {log_(FATAL, socket create fail , the errornum : %d\n, sockfd_);exit(SOCK_CREATE_FAIL);}log_(INFO, socket create sucess , sockfd : %d, sockfd_);// 绑定地址和端口struct sockaddr_in localsr;bzero(localsr, sizeof(localsr));localsr.sin_family AF_INET;localsr.sin_port htons(port_);localsr.sin_addr.s_addr INADDR_ANY;socklen_t locallen sizeof(localsr);if (bind(sockfd_, (const struct sockaddr *)localsr, locallen) 0) {log_(FATAL, socket bind fail, err string :%s, strerror(errno));exit(SOCK_BIND_FAIL);}log_(INFO, socket bind sucess , sockfd : %d, sockfd_);}// 运行服务器void Run(Echofunc_t EchoHandler) {isrunning_ true;char inbuf[BUF_SIZE] {0};while (isrunning_) {struct sockaddr_in client;socklen_t len sizeof(client);bzero(client, sizeof(client));// 接收客户端消息size_t n recvfrom(sockfd_, inbuf, sizeof(inbuf) - 1, 0,(struct sockaddr *)client, len);if (n 0) {log_(WARNING, recvfrom fail, err string :%s, strerror(errno));continue;}log_(INFO, recvfrom sucess);uint16_t port ntohs(client.sin_port); // 接收客户端数据并提取对应的IP和port将其序列化(网络字节序转主机字节序)std::string ip inet_ntoa(client.sin_addr);inbuf[n] 0;// 处理数据std::string info inbuf;std::string echo_string EchoHandler(inbuf, ip, port);std::cout echo_string std::endl;// 发送回复sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0,(const struct sockaddr *)client, len);}}private:int sockfd_; // 套接字文件描述符uint16_t port_; // 端口号bool isrunning_; // 运行状态static const uint16_t defaultport; // 默认端口
};// 设置默认端口
const uint16_t UdpServer::defaultport 8080;#endif 其中下面这段代码为接收到客户端所发的数据并提取对应的IP地址和端口号将其进行序列化,即网络字节序转主机字节序; uint16_t port ntohs(client.sin_port); // 接收客户端数据并提取对应的IP和port将其序列化(网络字节序转主机字节序)std::string ip inet_ntoa(client.sin_addr);UDP套接字简单群聊服务端 /* UdpServer.hpp */
#ifndef UDPSERVER_HPP
#define UDPSERVER_HPP#include arpa/inet.h
#include netinet/in.h
#include sys/socket.h
#include sys/types.h#include cstring
#include functional
#include iostream
#include string
#include unordered_map#include log.hpp#define BUF_SIZE 1024// 定义回调函数类型用于处理接收到的消息
using Echofunc_t std::functionstd::string(const std::string ,const std::string , uint16_t);Log log_;// 错误枚举用于标识不同的错误类型
enum { SOCK_CREATE_FAIL 1, SOCK_BIND_FAIL };class UdpServer {public:// 构造函数初始化服务器参数UdpServer(const uint16_t port defaultport): sockfd_(0), port_(port), isrunning_(false) {}// 析构函数~UdpServer() {}// 初始化服务器创建并绑定socketvoid Init() {// 创建UDP socketsockfd_ socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ 0) {log_(FATAL, socket create fail , the errornum : %d\n, sockfd_);exit(SOCK_CREATE_FAIL);}log_(INFO, socket create sucess , sockfd : %d, sockfd_);// 设置服务器地址结构struct sockaddr_in localsr;bzero(localsr, sizeof(localsr));localsr.sin_family AF_INET;localsr.sin_port htons(port_);localsr.sin_addr.s_addr INADDR_ANY;socklen_t locallen sizeof(localsr);// 绑定socket到指定地址和端口if (bind(sockfd_, (const struct sockaddr *)localsr, locallen) 0) {log_(FATAL, socket bind fail, err string :%s, strerror(errno));exit(SOCK_BIND_FAIL);}log_(INFO, socket bind sucess , sockfd : %d, sockfd_);}// 检查用户是否已存在如果是新用户则添加到在线用户列表void CheckUsr(const struct sockaddr_in client) {uint16_t port ntohs(client.sin_port);std::string ip inet_ntoa(client.sin_addr);// 检查用户是否首次登录auto it online_user_.find(ip);if (it online_user_.end()) {online_user_[ip] client;std::cout The ip first login... std::endl;}}// 向所有在线用户广播消息void Broadcast(const std::string info, const std::string ip,uint16_t port) {for (const auto usr : online_user_) {// 构造广播消息std::string massage [ ip : std::to_string(port) echo]# info;socklen_t len sizeof(usr.second);// 发送消息给每个在线用户sendto(sockfd_, massage.c_str(), massage.size(), 0,(struct sockaddr *)(usr.second), len);}}// 运行服务器处理接收到的消息void Run(Echofunc_t EchoHandler) {isrunning_ true;char inbuf[BUF_SIZE] {0};while (isrunning_) {// 接收客户端数据struct sockaddr_in client;socklen_t len sizeof(client);bzero(client, sizeof(client));size_t n recvfrom(sockfd_, inbuf, sizeof(inbuf) - 1, 0,(struct sockaddr *)client, len);if (n 0) {log_(WARNING, recvfrom fail, err string :%s, strerror(errno));continue;}// 解析客户端信息uint16_t port ntohs(client.sin_port);std::string ip inet_ntoa(client.sin_addr);inbuf[n] 0; // 确保字符串以null结尾// 检查并更新用户状态CheckUsr(client);std::string info inbuf;// 广播接收到的消息Broadcast(info, ip, port);}}private:int sockfd_; // socket文件描述符uint16_t port_; // 服务器端口bool isrunning_; // 服务器运行状态标志static const uint16_t defaultport; // 默认端口std::unordered_mapstd::string, struct sockaddr_in online_user_; // 在线用户列表
};const uint16_t UdpServer::defaultport 8080; // 设置默认端口为8080#endif 这段代码包含了必要的系统和标准库头文件; 构造函数 // 构造函数初始化服务器参数UdpServer(const uint16_t port defaultport): sockfd_(0), port_(port), isrunning_(false) {}用于初始化服务器的基本参数,包括套接字文件描述符,端口号,运行标识符; Init函数 void Init()创建UDP socket sockfd_ socket(AF_INET, SOCK_DGRAM, 0);创建一个UDP socket套接字,AF_INET表示使用IPv4,SOCK_DGRAM表示使用UDP协议,0表示默认协议; 如果创建失败记录错误并退出程序; 设置服务器地址结构 // 设置服务器地址结构struct sockaddr_in localsr;bzero(localsr, sizeof(localsr));localsr.sin_family AF_INET;localsr.sin_port htons(port_);localsr.sin_addr.s_addr INADDR_ANY;socklen_t locallen sizeof(localsr);创建sockadd_in结构体localsr并调用bzero清空结构体; 设置地址族为IPv4,设置端口并转网络字节序,同样的设置IP地址并转网络字节序; 绑定socket if (bind(sockfd_, (const struct sockaddr *)localsr, locallen) 0) {log_(FATAL, socket bind fail, err string :%s, strerror(errno));exit(SOCK_BIND_FAIL);}log_(INFO, socket bind sucess , sockfd : %d, sockfd_);将socket绑定到指定的端口和地址,绑定成功或失败都会使用日志插件打印对应信息; Run函数 void Run(Echofunc_t EchoHandler);该函数用于运行服务端,其中EchoHandler是一个回调函数,用于处理接收到的数据; 初始化 isrunning_ true;char inbuf[BUF_SIZE] {0};将运行状态设置为true,初始化inbuf数组用于接收数据; 主循环 while (isrunning_){/* ... */}服务端会持续运行直至isrunning_被设置为false; 接收数据 // 接收客户端数据struct sockaddr_in client;socklen_t len sizeof(client);bzero(client, sizeof(client));size_t n recvfrom(sockfd_, inbuf, sizeof(inbuf) - 1, 0,(struct sockaddr *)client, len);创建一个sockaddr_in结构体用来存储客户端地址信息,并调用bzro清空客户端地址结构; socklen_t len设置地址结构的长度; 使用recvfrom函数接收数据,并返回接收到的字节数给size_t n; 错误处理 if (n 0) {log_(WARNING, recvfrom fail, err string :%s, strerror(errno));continue;}如果recvfrom返回负值说明调用失败,记录错误并进行下一次循环; 处理接收到的数据 // 解析客户端信息uint16_t port ntohs(client.sin_port);std::string ip inet_ntoa(client.sin_addr);inbuf[n] 0; // 确保字符串以null结尾解析客户端的信息,包括IP,端口号等等; 如果n0说明数据接收成功,该值即为接收的长度,将数组对应的位置赋值0(即\0)将该数组看成是字符串; 检查更新用户状态 // 检查并更新用户状态CheckUsr(client);调用CheckUsr函数检查用户状态并进行更新; 广播消息 std::string info inbuf;// 广播接收到的消息Broadcast(info, ip, port);将接收到的消息调用Broadcast函数广播接收到的消息; CheckUsr检查更新用户函数 void CheckUsr(const struct sockaddr_in client);参数client表示传入一个地址结构,该地址结构保存客户端的信息; 解析客户端信息 uint16_t port ntohs(client.sin_port);std::string ip inet_ntoa(client.sin_addr);解析客户端信息,包括IP地址与端口号,将网络字节序转化为主机字节序; 检查用户是否存在 auto it online_user_.find(ip);if (it online_user_.end()) {online_user_[ip] client;std::cout The ip first login... std::endl;}该类中的unordered_mapstd::string, struct sockaddr_in online_user_存放着用户的信息,检查该哈希表中是否存在该用户的信息,有则无行为,无则添加; Broadcast广播消息函数 该函数用于遍历哈希表,将消息广播回当前在线的所有用户; 遍历哈希表(在线用户) for (const auto usr : online_user_){ /* ... */ }遍历所有在线用户; 构造广播消息 // 构造广播消息std::string massage [ ip : std::to_string(port) echo]# info;创建一个包含发送者IP,端口号和原始消息的格式化字符串; 发送消息 socklen_t len sizeof(usr.second);// 发送消息给每个在线用户sendto(sockfd_, massage.c_str(), massage.size(), 0,(struct sockaddr *)(usr.second), len);对每个在线的用户调用sendto函数发送构造的消息,其中sockfd_是服务器的socket; massage.c_str()和massage.size()用于提供消息内容和长度; (struct sockaddr *)(usr.second)为目标用户的地址;
/* Main.cc */
#include iostream
#include vector
#include UdpServer.hpp// 打印使用说明
void Usage(std::string proc) {std::cout \n\tUsage: proc port[1024]\n std::endl;
}// 回声处理函数
std::string EchoHandler(const std::string datastr, const std::string clientip, uint16_t clientport) {std::string echo_string [ clientip : std::to_string(clientport) echo]# datastr;return echo_string;
}int main(int argc, char* argv[]) {if (argc ! 2) {Usage(argv[0]);exit(0);}// 创建并初始化UDP服务器std::unique_ptrUdpServer svr(new UdpServer(std::stoi(argv[1])));svr-Init();// 运行服务器svr-Run(EchoHandler);return 0;
}EchoHandler函数 std::string EchoHandler(const std::string datastr, const std::string clientip, uint16_t clientport) {std::string echo_string [ clientip : std::to_string(clientport) echo]# datastr;return echo_string;
}这是一个回声处理函数,用于接收客户端发送的数据,客户端IP和端口号,然后构造一个包含这些信息的字符串并返回; main函数 // 创建并初始化UDP服务器std::unique_ptrUdpServer svr(new UdpServer(std::stoi(argv[1])));svr-Init();// 运行服务器svr-Run(EchoHandler);主函数创建并初始化UDP服务器随后运行; UDP套接字简单群聊客户端 /* UdpClient.hpp */
#include arpa/inet.h
#include netinet/in.h
#include pthread.h
#include sys/socket.h
#include sys/types.h
#include unistd.h#include cstring
#include iostream
#include memory
#include string// 线程数据结构用于在线程间传递必要的信息
struct ThreadData {sockaddr_in local; // 服务器地址信息int sockfd; // 套接字文件描述符
};// 打印使用说明
void Usage(std::string proc) {std::cout \n\tUsage: proc serverip serverport\n std::endl;
}// 接收消息的线程函数
void* recv_message(void* data) {ThreadData* td (ThreadData*)data;char buffer[1024] {0}; // 接收缓冲区while (true) {struct sockaddr_in temp;bzero(temp, sizeof(temp));socklen_t len sizeof(temp);// 接收来自服务器的消息ssize_t n recvfrom(td-sockfd, buffer, 1023, 0, (struct sockaddr*)temp, len);if (n 0) {buffer[n] 0; // 确保字符串正确终止std::cout buffer std::endl; // 打印接收到的消息}}
}// 发送消息的线程函数
void* send_message(void* data) {ThreadData* td (ThreadData*)data;std::string message;while (true) {std::cout Please Enter;getline(std::cin, message); // 获取用户输入socklen_t len sizeof(td-local);// 发送消息到服务器int sdebug sendto(td-sockfd, message.c_str(), message.size(), 0,(struct sockaddr*)td-local, len);if (sdebug 0) {std::cout sendto fail, err: strerror(errno) std::endl;}}
}int main(int argc, char* argv[]) {// 检查命令行参数if (argc ! 3) {Usage(argv[0]);exit(0);}std::string serverip argv[1];uint16_t serverport std::stoi(argv[2]);ThreadData tdata;// 初始化服务器地址结构bzero(tdata.local, sizeof(tdata.local));tdata.local.sin_family AF_INET;tdata.local.sin_port htons(serverport);tdata.local.sin_addr.s_addr inet_addr(serverip.c_str());// 创建UDP套接字tdata.sockfd socket(AF_INET, SOCK_DGRAM, 0);if (tdata.sockfd 0) {std::cout socket fail std::endl;exit(-1);}// 创建接收和发送线程pthread_t recver, sender;pthread_create(recver, nullptr, recv_message, tdata);pthread_create(sender, nullptr, send_message, tdata);// 等待线程结束实际上这里的线程不会结束pthread_join(recver, nullptr);pthread_join(sender, nullptr);// 关闭套接字实际上这行代码永远不会被执行close(tdata.sockfd);return 0;
} 这个客户端使用了双线程,即一个线程用于接收数据,一个线程用于发送数据以避免getline函数阻塞线程导致的无法正确接收消息; ThreadData结构体 定义了再线程间共享的数据结构,包含了服务器的地址信息和套接字描述符; // 线程数据结构用于在线程间传递必要的信息
struct ThreadData {sockaddr_in local; // 服务器地址信息int sockfd; // 套接字文件描述符
};recv_message函数 该函数主要用于接收从服务端中转发的数据; // 接收消息的线程函数
void* recv_message(void* data) {ThreadData* td (ThreadData*)data;char buffer[1024] {0}; // 接收缓冲区while (true) {struct sockaddr_in temp;bzero(temp, sizeof(temp));socklen_t len sizeof(temp);// 接收来自服务器的消息ssize_t n recvfrom(td-sockfd, buffer, 1023, 0, (struct sockaddr*)temp, len);if (n 0) {buffer[n] 0; // 确保字符串正确终止std::cout buffer std::endl; // 打印接收到的消息}}
}创建一个sockaddr_in结构体用于存储服务端的基本信息,而后调用recvfrom函数接收消息; 接收消息后将消息末尾处添加\0作字符串并进行打印; send_message函数 该函数为发送消息的线程函数,即循环读取用户输入信息而后调用sendto函数将消息发送到服务器; 循环读取用户输入信息 while (true) {std::cout Please Enter;getline(std::cin, message); // 获取用户输入socklen_t len sizeof(td-local);// ...}调用sendto函数发送消息 int sdebug sendto(td-sockfd, message.c_str(), message.size(), 0,(struct sockaddr*)td-local, len);if (sdebug 0) {std::cout sendto fail, err: strerror(errno) std::endl;}调用函数后判断消息是否成功发出; main函数 main函数首先检查命令行参数判断是否需要调用Usage用户手册; 初始化ThreadData结构体用于存储服务器对应信息; 创建UDP套接字并创建两个线程,一个用于接收消息,一个用于发送消息; 运行测试及分离输入输出 运行测试结果显示UDP网络通信成功,但这里的输入输出混在在一起; 可以将服务端转发的数据重定向到另一个窗口以实现单终端输入单中端输出; 使用ls /dev/pts查看当前主机下多少Bash存在;
$ ls /dev/pts
0 1 2 3 ptmx多个终端情况下使用echo hello /dev/pts/[cmdnumber]检查哪个终端将接收到数据从而指定哪个终端作为输入哪个作为输出;
$ echo hello world /dev/pts/1
hello world根据对应的终端号使用open打开该文件并调用dup2重定向到对应的文件(终端)中实现输入输出分离;
std::string terminal /dev/pts/1;int OpenTerminal() {int fd open(terminal.c_str(), O_WRONLY);if (fd 0) {std::cerr open terminal error std::endl;return 1;}dup2(fd, 2);return 0;
}由于该处dup2的文件描述符为2(标准错误流); 故在客户端中接收到服务端发出的数据应使用std::cerr进行打印;
void* recv_message(void* data) {// 接收缓冲区 ...while (true) {// 接收来自服务器的消息 ...std::cerr buffer std::endl; // 使用标准错误cerr打印接收到的消息}}
}结果如下: 参考代码 [Gitee - 半介莽夫 / Dio夹心小面包]
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/924007.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!