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

北京网站建设公司招聘国内猎头公司前十名

北京网站建设公司招聘,国内猎头公司前十名,广告创意设计是什么,做赚钱问卷调查的网站好今天我们通过以下的几个surver/client模型了解一下#xff35;#xff24;#xff30;网络通信 一、简单的服务器echo程序 以下部分内容转载自「网络编程」简单UDP网络通信程序的实现_socket udp-CSDN博客 1.1 服务端 首先明确#xff0c;这个简单的UDP网络程序分客户端…今天我们通过以下的几个surver/client模型了解一下网络通信 一、简单的服务器echo程序 以下部分内容转载自「网络编程」简单UDP网络通信程序的实现_socket udp-CSDN博客 1.1 服务端 首先明确这个简单的UDP网络程序分客户端和服务端所以我们要生成两个可执行程序一个是客户端的另一个是服务端的服务端充当的是服务器暂时实现的功能是客户端和服务端简单进行通信服务端要可以收到客户端发送给服务端的信息目前就先简单实现这样的功能 下面进行编写服务端的代码 1.1.1 创建套接字文件 先介绍创建套接字文件的函数socket socket函数 socket函数的作用是创建套接字文件TCP/UDP 均可使用该函数进行创建套接字man 2 socket查看 create an endpoint for communication创建通信端点即创建通信的一端 函数socket头文件#include sys/types.h#include sys/socket.h函数原型int socket(int domain, int type, int protocol);参数第一个参数domain套接字类型第二个参数type数据的传输方式第三参数protocol创建套接字的协议类别返回值套接字创建成功返回一个文件描述符创建失败返回-1错误码被设置socket系统调用接口是对传输层的文件系统级别的封装Linux下一切皆文件socket函数用于创建套接字文件描述符也就是说后续在进行网络读写时可以用文件接口进行字节流读写TCP协议的特点是面向字节流传输所以可以使用文件接口进行网络读写UDP协议的特点是面向数据报传输所以不适用文件接口的字节流读写UPD有自己专属的读写接口recvfrom和sendto socket函数的参数 1socket函数的第一个参数是domain用于创建套接字的类型该参数就相当于 struct sockaddr结构体的前16位即2字节 该domain参数的选项已经设置好了我们直接选用即可。该参数的选项很多我们常用的也就几个 如果要选择本地通信则选择 AF_UNIX如果要选择网络通信则选择 AF_INETIPv4或者 AF_INET6IPv6 “inet” 是Internet ProtocolIP的简写 2socket函数的第二个参数是type用于创建套接字时提供的数据传输方式 该参数的选项也是已经设置好了我们直接选用即可。该参数的选项很多我们常用的也就几个 如果是基于UDP的网络通信我们采用的就是 SOCK_DGRAM套接字数据报提供的用户数据报服务对应UDP的特点面向数据报如果是基于TCP的网络通信我们采用的就是 SOCK_STREAM流式套接字提供的是流式服务对应TCP的特点面向字节流 SOCK_DGRAM对应的英文socket datagram SOCK_STREAM对应的英文socket stream 3socket函数的第三个参数是protocol用于创建套接字的协议类别。 可以指明为TCP或UDP但该字段一般直接设置为0就可以了。 设置为0表示的就是默认此时会根据传入的前两个参数自动推导出你最终需要使用的是哪种协议 socket函数的返回值 套接字创建成功返回一个文件描述符创建失败返回-1同时错误码被设置 解释套接字创建成功返回一个文件描述符的问题 当我们调用socket函数创建套接字时实际相当于我们打开了一个“网络文件”而这个网络文件得底层硬件实际就是“网卡”文件描述符下标0、1、2依次被标准输入、标准输出以及标准错误占用如果程序没有打开其他文件当套接字创建成功时文件描述符下标为3的指针就指向了这个打开的 “网络文件”我们读取、发送数据就从这个 “网络文件” 进行读取和发送所以操作网络就像操作文件一般这个“网络文件”就是一个缓冲区 明确一点 按照TCP/IP四层模型来说自顶向下依次是应用层、传输层、网络层和数据链路层。而我们现在所写的代码都叫做用户级代码也就是说我们是在应用层编写代码因此我们调用的实际是下三层的接口而传输层和网络层都是在操作系统内完成的也就意味着我们在应用层调用的接口都叫做系统调用接口 1.1.2 填充套接字结构绑定端口 绑定端口的函数是bind函数 bind函数 bind函数的作用是绑定端口号TCP/UDP 均可使用进行该函数绑定端口man 2 bind查看 bind a name to a socket将名称绑定到套接字 函数bind头文件#include sys/types.h#include sys/socket.h函数原型int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数第一个参数sockfd文件描述符第二个参数addr套接字结构的地址第三参数addrlen套接字结构的大小返回值绑定成功返回0绑定失败返回-1同时错误码会被设置下面介绍bind函数的参数 1bind函数的第一个参数是sockfd是套接字文件的文件描述符 2bind函数的第二个参数是addr是套接字结构, 用于保存网络相关的属性信息比如IP地址、端口号等 该参数addr的类型是struct sockaddr *也就是如图的结构体 我们要做的工作就是定义一个 sockaddr_in 的结构体也就是上图的第二个结构体然后对该结构体进行内容填充填完就把给结构体传给第二个参数addr需要强制类型转换 套接字结构 sockaddr_in 我们看一下 sockaddr_in 结构体的定义 可以看到sockaddr_in 有以下几个成员类型 sin_family表示协议家族类型uint16_t。实际就是套接字类型(AF_INET, AF_UNIX等) sin_port表示端口号类型uint16_t。填充时需要转网络序列 sin_addr.s_addr表示IP地址类型uint32_t。填充时需要将字符串转4字节整形并转为网络序列 剩下的字段不关注 端口号不能随意绑定 需要注意的是不是所有的端口号都能成功绑定如0~1023号端口被系统保留用于一些特定的服务和应用程序系统端口不允许绑定。还有一些熟知端口同样也不要进行绑定。 不建议服务器绑定特定的IP地址 首先云服务器是不支持的绑定公网IP的如果使用虚拟机或者独立Linux系统那么IP地址是支持绑定的。 实际上一款网络服务器不建议指明绑定一个IP上面的服务端指定绑定一个IP是错误的用法 比如你运行服务端的机器上有多个网卡意味着你的服务端上有多个IP 一台服务器上端口号为8080的服务只有一个。这台服务器在接收数据时底层的多张网卡多个IP都有可能接收到数据而这些数据也都是要向上递送给8080服务的。此时如果服务端在绑定的时候是指明绑定的某一个IP地址那么此时服务端在接收数据的时候就只能从绑定IP对应的网卡接收数据而来自其他IP的数据是接收不到的。 推荐服务器绑定的IP是INADDR_ANY这是一个宏代表 0.0.0.0叫做任意地址绑定。绑定了该IP只要是发送给端口号为8080的服务的数据不管来自主机上的哪张网卡哪个IP系统都会可以将数据自底向上全部递送给服务端。 网络序列与主机序列之间的转换 #include arpa/inet.huint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);字符串IP和整型IP之间的转换 头文件#includesys/types.h#include arpa/inet.h#include netinet/in.h 函数原型// 点分十进制字符串 -- 网络整型// 分两步1.字符串转整型 2.主机转网络in_addr_t inet_addr(const char *cp); //最简单int inet_aton(const char* cp, struct in_addr* inp); //注意第二个参数传in_addr结构的地址即sin_addrint inet_pton(int af, const char* src, void* dst); //第一个参数是协议家族后两个参数和inet_aton相同// 网络整形 -- 点分十进制字符串// 分两步1.网络转主机 2.in_addr结构转字符串char *inet_ntoa(struct in_addr in); //函数内部将转换后的字符串保存在静态存储区因此该函数是不可重入函数存在线程安全问题。const char* inet_ntop(int ar, const void* src, char* dst, socklen_t size); //多线程环境下推荐使用inet_ntop该函数需由调用者提供缓冲区可以规避线程安全问题。参数1.协议家族 2.整型IP地址 3.字符串缓冲区地址 4.缓冲区大小1.1.3 从客户端接收数据 服务端要接收客户端发送的消息接收信息的函数是recvfrom recvfrom函数的作用是接收信息 receive a message from a socket从套接字接收消息 函数recvfrom头文件#include sys/types.h#include sys/socket.h函数原型ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);参数第一个参数sockfd文件描述符从哪个套接字文件去读数据第二个参数buf代表读上来的数据放到哪个缓冲区里面第三参数len缓冲区的长度第四个参数flags读取方式0代表阻塞式读取第五个参数src_addr数据发送方的套接字结构从哪读第六个参数addrlensrc_addr结构体的长度返回值成功返回接收到的字节数失败返回-1同时错误码会被设置。对等方执行有序关闭后返回值将为0socklen_t 是一个32位的无符号整数 第五个参数src_addr输出型参数数据发送方的套接字结构地址recvfrom接收到数据后将对端的套接字结构存入其中。从哪读 第六个参数addrlen输入输出型参数需要传入src_addr结构体的长度recvfrom接收到数据后将读取到的套接字结构的大小存入其中。 我们需要定义一个套接字结构struct sockaddr并置为空将地址强转后传给src_addr还需要定义一个结构长度socklen_t并初始化为套接字结构的大小将其地址传给addrlen。如果不关注数据的来源后两个参数可以设置为nullptr 1.1.4 服务端代码 udpServer.hpp #pragma once #include iostream #include cstring #include cerrno #include cstdlib #include string #include unistd.h #include strings.h #include sys/types.h #include sys/socket.h #include arpa/inet.h using namespace std;// 错误类型枚举 enum {UAGE_ERR 1,SOCKET_ERR,BIND_ERR };const static string defaultIp 0.0.0.0; const static int gnum 1024;class udpServer { public:udpServer(const uint16_t port, const string ip defaultIp): _port(port), _ip(ip){}// 初始化服务器void initServer(){// 1.创建套接字文件_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd -1){cerr socket error: errno : strerror(errno) endl;exit(SOCKET_ERR);}cout socket success: _sockfd endl;// 2.绑定端口// 2.1 填充套接字结构sockaddr_instruct sockaddr_in local;bzero(local, sizeof(local)); // 把 sockaddr_in结构体全部初始化为0local.sin_family AF_INET; // 未来通信采用的是网络通信local.sin_port htons(_port); // htons(_port)主机字节序转网络字节序// 绑定IP方法1INADDR_ANY// local.sin_addr.s_addr INADDR_ANY;//服务器的真实写法// 绑定IP方法2把外部的构造函数传参去掉使用我们自己定义的string defaultIp 0.0.0.0;local.sin_addr.s_addr inet_addr(_ip.c_str()); // 1.string类型转int类型 2.把int类型转换成网络字节序 这两个工作inet_addr已完成// 2.2 绑定int n bind(_sockfd, (struct sockaddr *)local, sizeof(local)); // 需要强转(struct sockaddr*)localif (n -1){cerr bind error: errno : strerror(errno) endl;exit(BIND_ERR);}// UDP server 预备工作完成}// 启动服务器void start(){// 服务器的本质就是一个死循环char buffer[gnum];for (;;){struct sockaddr_in peer;socklen_t len sizeof(peer);ssize_t s recvfrom(_sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)peer, len);if (s 0) // 接收成功{buffer[s] 0;// 发消息对方的IPstring clientip inet_ntoa(peer.sin_addr); // 直接传sin_addr结构体整数IP 转 字符串IP点分十进制IP// 发消息对方的端口号uint16_t clientport ntohs(peer.sin_port); // ntohs网络字节序转主机字节序// 发送的消息string message buffer;// 打印cout clientip [ clientport ] # message endl;}}}~udpServer(){}private:uint16_t _port; // 端口号string _ip; // ip地址int _sockfd; // 文件描述符 };udpServer.cc #include udpServer.hpp #include memory// 使用手册 // ./udpServer port static void Uage(string proc) {cout \nUage:\n\t proc local_port\n\n; }int main(int argc, char *argv[]) {if (argc ! 2){Uage(argv[0]);exit(UAGE_ERR);}uint16_t port atoi(argv[1]); // string to int//不需要传IP了std::unique_ptrudpServer usvr(new udpServer(port));usvr-initServer(); // 初始化服务器usvr-start(); // 启动服务器return 0; }1.1.5 几个网络相关的命令行工具 ifconfig 命令 ifconfiginterface configuration接口配置显示和配置网络接口的信息 第一个IPinet 10.0.4.14这个IP是内网IP 第二个IP inet 127.0.0.1这个IP是本地环回用于本地测试 注“inet” 是Internet ProtocolIP的简写 什么是本地环回 所谓本地环回是指client和server发送数据只在本地协议栈中进行数据流动不会把我们的数据发送到网络中通常用于本地网络服务器测试通过本地环回测试的程序后期仍无法通信大概率是网络问题而非编码问题。本地环回地址通常是127.0.0.1 netstat 命令 netstat是一个用于显示网络连接、路由表和网络接口信息的命令行工具 netstatnetwork statistics网络统计 常用选项 -aall (显示所有连接和监听端口)-ttcp (仅显示TCP连接)-uudp (仅显示UDP连接)-nnumeric (以数字形式显示IP地址和端口号)-pprogram (显示与连接关联的进程信息)-llisten显示所有的监听端口-rroute (显示路由表信息)-sstatistics (显示网络统计信息) netstat -nuap 查看本机所有的udp连接 Foreign Address外部地址是指与本地计算机建立网络连接的远程计算机的IP地址和端口号也就是客户端连服务器 0.0.0.0:* 表示任意IP地址、任意的端口号的程序都可以访问当前进程 1.2 客户端 1.2.1 关于客户端的绑定问题 明确一点 客户端是需要服务端的IP和端口号的没有这些客户端就连不上服务端也就是说服务端的 IP 和端口号是不能轻易改变的否则用户端不知道就会连不上服务端所以现在我们写的需要手动传入服务端的IP和端口号 关于客户端的绑定问题 首先由于是网络通信通信双方都需要找到对方因此服务端和客户端都需要绑定各自的IP地址和端口号。只不过服务端需要指定端口号进行显式地绑定而客户端不需要显式地绑定端口号。服务器的IP端口号需要保证唯一性、固定性和公开性因此显示绑定端口号就是要将服务器的端口号固定下来。不管服务器重新启动多少次端口号都不会改变。而客户端的IP端口号只要保证唯一性就可以了端口号不需要进行固定。如果客户端绑定了某个端口号那么以后这个端口号就只能给这一个客户端使用如果被其他程序抢占该客户端就无法联网了。总之客户端不需要显示的绑定端口号在首次发送数据的时候操作系统会为该客户端进程分配空闲的端口号进行绑定也就是说客户端每次启动时使用的端口号可能是变化的此时只要客户端的端口号没有被耗尽客户端就永远可以启动 1.2.2 向服务端发送消息 客户端要发送消息给服务端发送消息的函数是sendto sendto函数的作用是发送消息 send a message on a socket在套接字上发送消息 函数sendto头文件#include sys/types.h#include sys/socket.h函数原型ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);参数第一个参数sockfd文件描述符从哪个套接字去发送消息第二个参数buf待写入数据的存放位置第三参数len写入数据的长度第四个参数flags写入方式0代表阻塞式写入第五个参数dest_addr数据接收方的套接字结构发给谁第六个参数addrlendest_addr结构体的长度返回值成功返回写入的字节数失败返回-1同时错误码会被设置第五个参数dest_addr输入型参数数据接收方的套接字结构的地址需要提前填充。发给谁 第六个参数addrlen输入型参数dest_addr结构体的长度。 我们要做的工作就是定义一个 sockaddr_in 的结构体然后对该结构体进行内容填充填完就把给结构体地址传给第五个参数dest_addr需要强制类型转换 1.2.3 客户端代码 udpClient.hpp #pragma once #include iostream #include cstring #include cerrno #include cstdlib #include string #include unistd.h #include strings.h #include sys/types.h #include sys/socket.h #include arpa/inet.h using namespace std;class udpClient { public:udpClient(const string serverip, const uint16_t serverport): _serverip(serverip), _serverport(serverport), _sockfd(-1), _quit(false){}// 初始化客户端void initClient(){// 创建套接字文件_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd -1){cerr socket error: errno : strerror(errno) endl;exit(2);}cout socket success: _sockfd endl;}// 启动客户端void run(){// 填充数据接收方的套接字结构服务端)struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(_serverport);//主机转网络序列server.sin_addr.s_addr inet_addr(_serverip.c_str());// 1.string类型转int类型 2.把int类型转换成网络字节序 这两个工作inet_addr已完成string message;while ((!_quit)){cout Please Enter# ;cin message;sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)server, sizeof(server));}}~udpClient(){}private:uint16_t _serverport; // 端口号string _serverip; // ip地址int _sockfd; // 文件描述符bool _quit; };udpClient.cc #include udpClient.hpp #include memory// 使用手册 // ./udpClient ip port static void Uage(string proc) {cout \nUage:\n\t proc server_ip server_port\n\n; }int main(int argc, char *argv[]) {if (argc ! 3){Uage(argv[0]);exit(1);}// 客户端需要服务端的 IP 和 portstring serverip argv[1];uint16_t serverport atoi(argv[2]); // string to intstd::unique_ptrudpClient ucli(new udpClient(serverip, serverport));ucli-initClient(); // 初始化服务器ucli-run(); // 启动服务器return 0; }二、简单的远程控制程序 2.1 popen、pclose函数 原理client向server发送shell命令再由server调用popen执行命令最后server将命令的执行结果返回给客户端。 popen函数 popen函数是用于创建一个子进程执行命令并打开一个管道与该进程进行通信。该函数的原型如下 #include stdio.hFILE *popen(const char *command, const char *type);其中command参数是一个以null结尾的字符串包含shell命令来执行。type参数是一个r或w的字符串用于指定管道的方向。 popen函数返回一个文件指针(FILE*)这个指针指向由command命令生成的进程的标准输入或标准输出重定向到管道文件。调用popen函数会创建一个新的进程并且返回一个文件指针可以对其进行读或写操作。 pclose函数 pclose函数是用于关闭由popen函数打开的管道并等待子进程结束。该函数的原型如下 #include stdio.hint pclose(FILE *stream);其中stream参数是由popen函数返回的文件指针。pclose函数会等待子进程结束并返回子进程的终止状态。 popen和pclose函数通常用于在一个进程中执行外部命令并与该命令进行输入输出的交互。这对于一些需要执行外部命令的操作非常有用比如执行shell命令并获取输出结果。 2.2 程序代码 对上一个程序的代码做一些小小的改动即可 udpServer::Start void Start(){char buffer[1024]; // 网络输入缓冲区std::string mesg; // 回复给客户端的命令执行结果for (;;){sockaddr_in client; // 输出型参数socklen_t len sizeof(client); // 输入输出型参数输入client缓冲器的大小输出实际读到的client的大小memset(client, 0, sizeof(client));ssize_t s recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)client, len);if (s 0){buffer[s] 0;// 过滤非法请求if (strcasestr(buffer, rm) ! nullptr){mesg 坏人... ;mesg buffer;sendto(_sockfd, mesg.c_str(), mesg.size(), 0, (sockaddr *)client, len);continue;}// 打印控制命令std::string client_ip inet_ntoa(client.sin_addr); // 注意inet_ntoa的参数是sin_addr结构uint16_t client_port ntohs(client.sin_port);printf([%s:%d]# %s\n, client_ip.c_str(), client_port, buffer);// 执行控制命令FILE *fp popen(buffer, r);if (fp nullptr){LogMessage(ERROR, (%d)%s, errno, strerror(errno));mesg error: (;mesg std::to_string(errno);mesg );mesg strerror(errno);sendto(_sockfd, mesg.c_str(), mesg.size(), 0, (sockaddr *)client, len);continue;}// 收集执行结果char ret[128]; // 临时缓冲区mesg.clear();while (fgets(ret, sizeof(ret), fp) ! nullptr){mesg ret;}// 一定要使用pclose关闭popen返回的文件流pclose(fp);}// 返回控制命令的执行结果sendto(_sockfd, mesg.c_str(), mesg.size(), 0, (sockaddr *)client, len);}}udpClient::Run void Run(){ sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(_serverport);server.sin_addr.s_addr inet_addr(_serverip.c_str());char buffer[1024];while (true){//1.获取命令printf(Please Enter$ );fgets(buffer, sizeof(buffer), stdin);buffer[strlen(buffer) - 1] \0; // 删除换行符if (strcmp(buffer, quit) 0){break;}//2.将命令发送给服务端// 当client首次给server发送数据时OS会自动给client绑定IP地址和端口号ssize_t s sendto(_sockfd, buffer, strlen(buffer), 0, (sockaddr *)server, sizeof(server));if (s -1){LogMessage(ERROR, (%d)%s, errno, strerror(errno));continue;}//3.接收服务端返回的执行结果sockaddr_in temp;memset(temp, 0, sizeof(temp));socklen_t len sizeof(temp);s recvfrom(_sockfd, buffer, sizeof(buffer)-1, 0, (sockaddr*)temp, len);if(s0){buffer[s] 0;printf(server:\n%s\n, buffer);}}}三、简单的网络聊天室程序 3.1 工作原理 client启动时会自动向server发送一条login消息此时server根据来源记录用户信息用户上线client将消息发送给serverserver再将消息转发给所有的在线用户。直到client退出自动向server发送一条quit消息此时server根据来源删除对应的用户记录用户下线。client的读写功能分离创建两个子线程分别完成读写操作使得消息的发送和接收功能可以并发执行。 注意无论是多线程读还是写使用的_sockfd都是同一个套接字文件描述符。也就是说UDP协议是全双工的可以同时进行收发而不受干扰。这是因为底层有两个缓冲区一个是读缓冲区一个是写缓冲区。 3.2 程序代码 udp_server.hpp #ifndef __UDP_SEVER_HPP__ #define __UDP_SEVER_HPP__ #include ...class UdpServer {int _sockfd;uint16_t _port;std::string _ip;std::unordered_mapstd::string, sockaddr_in _users; //在线用户列表public:UdpServer(const std::string ip, const uint16_t port): _ip(ip),_port(port),_sockfd(-1){}void InitServer(){//同第一个echo程序...}void Start(){char buffer[1024];char username[64];char msg[1024];for (;;){// 接收消息sockaddr_in client; // 输出型参数socklen_t len sizeof(client); // 输入输出型参数输入client缓冲器的大小输出实际读到的client的大小memset(client, 0, sizeof(client));ssize_t s recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)client, len);if (s 0){buffer[s] 0;std::string client_ip inet_ntoa(client.sin_addr); // 注意inet_ntoa的参数是sin_addr结构uint16_t client_port ntohs(client.sin_port);snprintf(username, sizeof(username), %s:%d, client_ip.c_str(), client_port);snprintf(msg, sizeof(msg), [%s]# %s, username, buffer);// 添加在线用户if (_users.find(username) _users.end()){LogMessage(NORMAL, %s log in!, username);_users.insert({username, client});}printf(%s\n, msg);}// 群发消息for (auto user : _users){LogMessage(NORMAL, push message: %s, user.first.c_str());sendto(_sockfd, msg, sizeof(msg), 0, (sockaddr *)user.second, sizeof(user.second));}// 用户退出删除在线用户if (strcmp(buffer, quit) 0){LogMessage(NORMAL, %s log out!, username);_users.erase(username);}}}~UdpServer(){if (_sockfd 0)close(_sockfd);} };#endifudp_client.cc #include ...int main(int argc, char *argv[]) {std::string serverip 43.143.194.141;uint16_t serverport 8080;//创建客户端对象UdpClient udpcli(serverip, serverport);udpcli.InitClient();//创建两个子线程分别完成读写操作使得消息的发送和接收功能可以并发执行。std::thread t1(UdpClient::SendMsg, udpcli);std::thread t2(UdpClient::RecvMsg, udpcli);t1.join();t2.join();return 0; } udp_client.hpp #pragma once#include ...class UdpClient {int _sockfd;std::string _serverip;uint16_t _serverport;bool _quit;public:UdpClient(const std::string ip, const uint16_t port): _serverip(ip),_serverport(port),_sockfd(-1),_quit(false){}void InitClient(){//同第一个echo程序...}void SendMsg(){sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(_serverport);server.sin_addr.s_addr inet_addr(_serverip.c_str());char buffer[1024] login;bool first true; //client启动时会自动向server发送一条login消息while (!_quit){if (!first){printf(Please Enter$ );fgets(buffer, sizeof(buffer), stdin);buffer[strlen(buffer) - 1] \0; // 删除换行符}first false;if (strcmp(buffer, quit) 0){_quit true;}if (strlen(buffer) 1)continue;// 当client首次给server发送数据时OS会自动给client绑定IP地址和端口号ssize_t s sendto(_sockfd, buffer, strlen(buffer), 0, (sockaddr *)server, sizeof(server));if (s -1){LogMessage(ERROR, (%d)%s, errno, strerror(errno));continue;}}}void RecvMsg(){char buffer[1024];while (!_quit){// sockaddr_in temp;// memset(temp, 0, sizeof(temp));// socklen_t len sizeof(temp);// ssize_t s recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)temp, len);ssize_t s recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, nullptr, nullptr);if (s 0){buffer[s] 0;fprintf(stderr, %s\n); //将接收的的消息打印到标准错误}}}~UdpClient(){if (_sockfd 0)close(_sockfd);} };为了分屏进行输入和输出可以将标准错误2号文件重定向到其他终端进行显示 提示可以在/dev/pts目录下查看其他打开的终端字符设备文件
文章转载自:
http://www.morning.kztpn.cn.gov.cn.kztpn.cn
http://www.morning.gqksd.cn.gov.cn.gqksd.cn
http://www.morning.kndt.cn.gov.cn.kndt.cn
http://www.morning.ljhnn.cn.gov.cn.ljhnn.cn
http://www.morning.hhfqk.cn.gov.cn.hhfqk.cn
http://www.morning.ldmtq.cn.gov.cn.ldmtq.cn
http://www.morning.jxzfg.cn.gov.cn.jxzfg.cn
http://www.morning.rfzbm.cn.gov.cn.rfzbm.cn
http://www.morning.xfmzk.cn.gov.cn.xfmzk.cn
http://www.morning.rnqyy.cn.gov.cn.rnqyy.cn
http://www.morning.ttdbr.cn.gov.cn.ttdbr.cn
http://www.morning.c7501.cn.gov.cn.c7501.cn
http://www.morning.yrnyz.cn.gov.cn.yrnyz.cn
http://www.morning.gyzfp.cn.gov.cn.gyzfp.cn
http://www.morning.xwlhc.cn.gov.cn.xwlhc.cn
http://www.morning.qqbw.cn.gov.cn.qqbw.cn
http://www.morning.rdxp.cn.gov.cn.rdxp.cn
http://www.morning.xjkr.cn.gov.cn.xjkr.cn
http://www.morning.kzcfp.cn.gov.cn.kzcfp.cn
http://www.morning.sqqdy.cn.gov.cn.sqqdy.cn
http://www.morning.gwhjy.cn.gov.cn.gwhjy.cn
http://www.morning.hkchp.cn.gov.cn.hkchp.cn
http://www.morning.nkrmh.cn.gov.cn.nkrmh.cn
http://www.morning.kqwsy.cn.gov.cn.kqwsy.cn
http://www.morning.ryzgp.cn.gov.cn.ryzgp.cn
http://www.morning.lczxm.cn.gov.cn.lczxm.cn
http://www.morning.pypbz.cn.gov.cn.pypbz.cn
http://www.morning.hympq.cn.gov.cn.hympq.cn
http://www.morning.hkswt.cn.gov.cn.hkswt.cn
http://www.morning.ylpl.cn.gov.cn.ylpl.cn
http://www.morning.nwjd.cn.gov.cn.nwjd.cn
http://www.morning.rsmtx.cn.gov.cn.rsmtx.cn
http://www.morning.yrbq.cn.gov.cn.yrbq.cn
http://www.morning.yhwxn.cn.gov.cn.yhwxn.cn
http://www.morning.zwdrz.cn.gov.cn.zwdrz.cn
http://www.morning.zsyrk.cn.gov.cn.zsyrk.cn
http://www.morning.qrwnj.cn.gov.cn.qrwnj.cn
http://www.morning.ckhry.cn.gov.cn.ckhry.cn
http://www.morning.zlkps.cn.gov.cn.zlkps.cn
http://www.morning.bcdqf.cn.gov.cn.bcdqf.cn
http://www.morning.rxkq.cn.gov.cn.rxkq.cn
http://www.morning.hybmz.cn.gov.cn.hybmz.cn
http://www.morning.bmmyx.cn.gov.cn.bmmyx.cn
http://www.morning.nlywq.cn.gov.cn.nlywq.cn
http://www.morning.rpgdd.cn.gov.cn.rpgdd.cn
http://www.morning.wjqyt.cn.gov.cn.wjqyt.cn
http://www.morning.sqlh.cn.gov.cn.sqlh.cn
http://www.morning.clfct.cn.gov.cn.clfct.cn
http://www.morning.lrybz.cn.gov.cn.lrybz.cn
http://www.morning.ykwgl.cn.gov.cn.ykwgl.cn
http://www.morning.mlwpr.cn.gov.cn.mlwpr.cn
http://www.morning.pqqxc.cn.gov.cn.pqqxc.cn
http://www.morning.kpypy.cn.gov.cn.kpypy.cn
http://www.morning.przc.cn.gov.cn.przc.cn
http://www.morning.qtrlh.cn.gov.cn.qtrlh.cn
http://www.morning.kdnbf.cn.gov.cn.kdnbf.cn
http://www.morning.lggng.cn.gov.cn.lggng.cn
http://www.morning.huayaosteel.cn.gov.cn.huayaosteel.cn
http://www.morning.pmjhm.cn.gov.cn.pmjhm.cn
http://www.morning.btwlp.cn.gov.cn.btwlp.cn
http://www.morning.nqbs.cn.gov.cn.nqbs.cn
http://www.morning.sbrjj.cn.gov.cn.sbrjj.cn
http://www.morning.hyryq.cn.gov.cn.hyryq.cn
http://www.morning.kgfsz.cn.gov.cn.kgfsz.cn
http://www.morning.gyzfp.cn.gov.cn.gyzfp.cn
http://www.morning.pmsl.cn.gov.cn.pmsl.cn
http://www.morning.gktds.cn.gov.cn.gktds.cn
http://www.morning.jkrrg.cn.gov.cn.jkrrg.cn
http://www.morning.frfnb.cn.gov.cn.frfnb.cn
http://www.morning.jykzy.cn.gov.cn.jykzy.cn
http://www.morning.msbmp.cn.gov.cn.msbmp.cn
http://www.morning.znknj.cn.gov.cn.znknj.cn
http://www.morning.nbmyg.cn.gov.cn.nbmyg.cn
http://www.morning.tfgkq.cn.gov.cn.tfgkq.cn
http://www.morning.gwkjg.cn.gov.cn.gwkjg.cn
http://www.morning.lpgw.cn.gov.cn.lpgw.cn
http://www.morning.lsfzq.cn.gov.cn.lsfzq.cn
http://www.morning.srmpc.cn.gov.cn.srmpc.cn
http://www.morning.rlqwz.cn.gov.cn.rlqwz.cn
http://www.morning.jpqmq.cn.gov.cn.jpqmq.cn
http://www.tj-hxxt.cn/news/259990.html

相关文章:

  • 哈尔滨网站建设自助建站做网站还是做业务员
  • 网站权重怎么查询淘宝联盟怎么建设网站
  • 在阿里云服务器做淘客网站免费软件加速器
  • 网站建设与应用 教案坪山网站建设行情
  • 做包子网站彩票网站开发制作
  • 网站制作培训wordpress主题 m1
  • 木材模板.网站网站建设华为
  • 赤峰做企业网站公司购物网站每个模块主要功能
  • 网站建设需要懂什么语言上国外的网站很慢
  • 网站首页动图怎么做营销师
  • 网站建设图片怎么调高端网站建设过程
  • 中国建设银行理财网站宣威做网站建设的公司
  • 网页制作公司 软件周口seo公司
  • 重庆网站推广免费软件wordpress主题设计师导航
  • ja.wordpress.org漳州seo网站快速排名
  • 学校网站建设学生文明上网网站开发 cms
  • 花店网站模板小程序开发费用多少
  • 如何用模板搭建网站询盘网站
  • 国外电商网站如何建立温州专业营销网站制作
  • 登封市建设局网站欧美风格网站模版
  • 住房及城乡建设部网站九大员网站网页直播怎么做的
  • 西安比较好的网络公司专业网站优化培训
  • 旅游网站设计与分析程序员培训机构有哪些
  • 集团网站建设方案广告传媒公司营业执照经营范围
  • 可信网站代码网站注册界面
  • 开发网站培训班wordpress 升级 无法创建目录
  • 企业网站建设与实施调研报告基本情况常熟网络推广
  • 商务网站建设定义赣州百度
  • 网页设计项目报告总结整站优化全网营销
  • 国家森林公园网站建设做的比较好的网站推荐