【计算机网络】UDP网络程序

一、服务端

1.udpServer.hpp

此文件负责实现一个udp服务器

#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>// 默认参数
static const std::string defaultIp = "0.0.0.0";
static const int gnum = 1024;// 回调函数类型
typedef std::function<void (int, std::string, uint16_t, std::string)> func_t;// 错误码
enum
{USAGE_ERR = 1,SOCKET_ERR,BIND_ERR,OPEN_ERR
};// udp服务器
class udpServer
{
public:// 构造函数udpServer(func_t &callback, uint16_t &port, std::string &ip = defaultIp):_callback(callback), _port(port), _ip(ip), _sockfd(-1){}// 析构函数~udpServer(){}// 初始化服务器void initServer();// 启动服务器void start();private:uint16_t _port;  // 服务器进程的端口号std::string _ip; // 服务器的IP 一款网络服务器不建议指明一个IPint _sockfd;     // 创建socket后返回的文件描述符,利用这个fd进行读写func_t _callback;// 回调函数:利用这个函数处理业务
};

(1)initServer()

void initServer()
{// 1. 创建socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd == -1){cerr << "socket error" << errno << " : " << strerror(errno) << endl;exit(SOCKET_ERR);}std::cout << "socket success" << " : " << _sockfd << std::endl;// 2. 绑定 port ip// 未来服务器要明确的port,不能随意改变struct sockaddr_in local;bzero(&local, sizeof(local)); // 初始化结构体为全0local.sin_family = AF_INET;// 你如果要给别人发消息,你的port和ip要发送给对方// 所以port和ip要从当前主机到网络 h -> nlocal.sin_port = htons(_port); // 1.string->uint32_t  2.htonl() -> inet_addr函数local.sin_addr.s_addr = inet_addr(_ip.c_str()); // local.sin_addr.s_addr = htonl(INADDR_ANY);// 任意地址bind:INADDR_ANY:全0// 把创建的fd和端口号绑定int n = bind(_sockfd, (struct sockaddr *)&local, sizeof(local));if (n == -1){cerr << "bind error" << errno << " : " << strerror(errno) << endl;exit(BIND_ERR);}// UDP Server 的预备工作完成
}

(2)start()

void start()
{// 服务器的本质其实就是一个死循环char buffer[gnum]; // 读到的数据放这里for (;;){// 读取数据struct sockaddr_in peer;socklen_t len = sizeof(peer);                                                                 // recvfrom读取数据ssize_t s = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);// 处理数据if (s > 0){// 1.知道是谁发的std::string clientip = inet_ntoa(peer.sin_addr); // IPuint16_t clientport = ntohs(peer.sin_port); // 端口号// 2.知道发的什么buffer[s] = '\0';std::string message = buffer;cout << clientip << "[" << clientport << "]# " << message << endl;// 我们只把数据读上来就完了吗?还需要对数据做处理_callback(_sockfd, clientip, clientport, message);}}
}

2.udpServer.cpp

此文件负责udp服务器的调用逻辑

#include "udpServer.hpp"
#include <cstdio>
#include <memory>
#include <fstream>
#include <signal.h>// 使用手册
void Usage(std::string proc)
{std::cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}// 对收到的数据做处理
void handlerMessage(int sockfd, std::string clinetip, uint16_t clientport, std::string message)
{// 填写客户端信息struct sockaddr_in client;bzero(&client, sizeof(client));client.sin_family = AF_INET;client.sin_port = htons(clientport);client.sin_addr.s_addr = inet_addr(clinetip.c_str());// 处理并发送消息(服务器 -> 客户端)string response_message = "I am server, i receive you message: " + message;sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr *)&client, sizeof(client));
}// ./udpServer port
int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);exit(USAGE_ERR);}uint16_t port = atoi(argv[1]);std::unique_ptr<udpServer> usvr(new udpServer(handlerMessage, port));usvr->initServer();usvr->start();return 0;
}

二、客户端

1.udpClient.hpp

此文件负责实现一个udp客户端

#pragma once#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>class udpClient
{
public:// 构造函数udpClient(std::string &serverIp, const uint16_t &serverPort): _serverIp(serverIp), _serverPort(serverPort), _sockfd(-1), _quit(false){}// 析构函数~udpClient(){}// 初始化客户端void initClient()// 这个线程负责 接受消息static void *readMessage(void *args)// 主线程负责 发送消息void run()private:int _sockfd;           // 自己的fdstd::string _serverIp; // 目的地uint16_t _serverPort;  // 目的地bool _quit;            // 表明是否退出pthread_t _reader; // 这个线程负责 读取消息
};

(1)initClient()

void initClient()
{// 1.创建socket_sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd == -1){cerr << "socket error" << errno << " : " << strerror(errno) << endl;exit(2);}std::cout << "socket success" << " : " << _sockfd << std::endl;// 2.client要不要bind?要;client要不要显示的bind/程序员自己bind?不需要// 写服务器的是一家公司,写client是无数家公司 -- 有OS自动形成端口进行bind!// client只要有端口号就行,而server的端口号一定要是明确的,众所周知的// bind:让文件信息 和 网络端口 产生关联
}

(2)run()

// 主线程负责 发送消息
void run()
{pthread_create(&_reader, nullptr, readMessage, (void *)&_sockfd);// 填写 要发送到的服务器的信息struct sockaddr_in server;memset(&server, 0, sizeof(server));server.sin_family = AF_INET;server.sin_addr.s_addr = inet_addr(_serverIp.c_str()); // 1.string->uint32_t  2.htonl()server.sin_port = htons(_serverPort);// 发送信息std::string message;char cmdline[1024];while (!_quit){// std::cout << "Please Enter# ";// 这种输入:重点在于可以输入空格fgets(cmdline, sizeof(cmdline), stdin);cmdline[strlen(cmdline) - 1] = '\0'; // 处理掉输入进来的回车message = cmdline;sendto(_sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, sizeof(server)); // 发送消息// 没有显示绑定时,第一次发消息的时候绑定port}
}

(3)readMessage()

// 这个线程负责 接受消息
static void *readMessage(void *args)
{int sockfd = *(static_cast<int *>(args));pthread_detach(pthread_self());while (true){// 接收服务器返回的结果char buffer[1024]; // 接收到的信息存储到buffer中struct sockaddr_in temp;socklen_t temp_len = sizeof(temp);size_t n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&temp, &temp_len);if (n >= 0)buffer[n] = '\0';std::cout << buffer << std::endl;}return nullptr;
}

2.udpClient.cpp

此文件负责udp客户端的调用逻辑

#include "udpClient.hpp"
#include <memory>// 使用手册
void Usage(std::string proc)
{std::cout << "\nUsage:\n\t" << proc << " server_ip server_port\n\n";
}// ./udpClient server_ip server_port -> 输入目的地址(服务器地址)
int main(int argc, char *argv[])
{if(argc != 3){Usage(argv[0]);exit(1);}std::string serverIp = argv[1];uint16_t serverPort = atoi(argv[2]);std::unique_ptr<udpClient> ucli(new udpClient(serverIp, serverPort));ucli->initClient();ucli->run();return 0;
}

三、整体调用逻辑

123

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60579.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【027B】基于51单片机模拟电梯(点阵)【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统8*8点阵显示按键设置LED灯。 1、设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff1b; 2、采用8*8点阵显示楼层和电梯运作&#xff08;上升、下降&#xff09;指示&#xff0c;同时具有八个楼层指示灯&#xf…

nginx openresty lua-resty-http 使用的一些问题记录

需求背景 需求是使用 nginx 做一个 https 服务的代理 nginx 收到 http 请求后&#xff0c;需要修改 body 中的某些参数值&#xff0c;然后将修改后的数据发送到目标服务器&#xff08;https&#xff09; 本来以为很简单的需求&#xff0c;结果中间出现了不少岔子&#xff0c;这…

vue2+ element ui 集成pdfjs-dist

目录 1. 下载Pdf.js1.1 下载1.2 修改配置1.2.1 将pdfjs-3.8.162-dist复制到项目中1.2.2 解决跨域问题1.2.3 将pdf.worker.js文件复制到public目录下1.2.4 安装 pdfjs-dist1.2.5 前端vue代码(示例) 3. 参考资料 1. 下载Pdf.js 1.1 下载 下载链接&#xff08;官方&#xff09;需…

「Mac玩转仓颉内测版2」入门篇2 - 编写第一个Cangjie程序

本篇详细介绍在Mac系统上创建首个Cangjie项目并编写、运行第一个Cangjie程序的全过程。内容涵盖项目创建、代码编写、程序运行与调试&#xff0c;以及代码修改后的重新运行。通过本篇&#xff0c;掌握Cangjie项目的基本操作&#xff0c;进一步巩固开发环境的配置&#xff0c;迈…

@ComponentScan 和 @SpringBootApplication 同时使用出现问题

1 同时使用ComponentScan和SpringBootApplication&#xff0c;会导致SpringBootApplication所带的注解失效&#xff0c;请注意这个问题。我在使用mybatis时出现了找不到bean的问题&#xff0c;使用了ComponentScan导致Controller没有扫描到。 2 在springboot下使用mybatis时&a…

接单渠道,程序员看这篇就够了。

接单、兼职&#xff0c;有团队没单子&#xff1f;僧多粥少&#xff0c;苦矣。 很多程序员&#xff0c;有时间、有技术&#xff0c;有steam&#xff08;咳咳&#xff0c;不对&#xff0c;是team&#xff09;。但是&#xff0c;可能还是挣不到什么钱&#xff0c;何也&#xff1f…

【深度学习】使用硬件加速模型训练速度

一、 单机器单GPU 特点 配置简单&#xff1a;无需多 GPU 或分布式环境的复杂配置&#xff0c;适合资源有限的场景。适合小规模模型&#xff1a;对于计算量不大的模型&#xff08;如中小型 CNN、RNN&#xff09;&#xff0c;单 GPU 可以处理大多数常见任务。 优势 简单易用&…

CSS:导航栏三角箭头

用CSS实现导航流程图的样式。可根据自己的需求进行修改&#xff0c;代码精略的写了一下。 注&#xff1a;场景一和场景二在分辨率比较低的情况下会有一个1px的缝隙不太优雅&#xff0c;自行处理。有个方法是直接在每个外面包一个DIV&#xff0c;用动态样式设置底色。 场景一、…

Qt_day4_Qt_UI设计

目录 Qt_UI设计 1. Designer 设计师&#xff08;掌握&#xff09; 2. Layout 布局&#xff08;重点&#xff09; 2.1 基本使用 2.2 高级用法 2.3 代码布局&#xff08;了解&#xff09; 3. Designer与C的关系&#xff08;熟悉&#xff09; 4. 基本组件&#xff08;掌握…

sql专题 之 count()区别

文章目录 count&#xff08;1&#xff09;count(*)count(列名)比较 count&#xff08;1&#xff09; count(1) 是对结果集中的每一行计数&#xff0c;不关注具体的列&#xff0c;只是计数行数。 每一行都计为常数1 等同于 count(*)&#xff0c;性能上基本一致&#xff0c;但有时…

嵌入式课程day14-C语言指针进阶

目录 10.3指针进阶 10.3.1数组指针 10.3.2指针数组 10.3.3函数指针 10.3.4指针函数 10.3.5函数指针的实际应用案例qsort函数&#xff1a; 10.3指针进阶 10.3.1数组指针 是指针 --- 指向对象的类型是 数组 int [3] 数组指针一般用于指向二维数组里面的一行&#xff0c;…

蓝桥杯模拟

【问题描述】 如果一个数 p 是个质数&#xff0c;同时又是整数 a 的约数&#xff0c;则 p 称为 a 的一个质因数。 请问 2024 有多少个质因数。 【答案提交】 这是一道结果填空的题&#xff0c;你只需要算出结果后提交即可。本题的结果为一个整数&#xff0c;在提交答案时只…

Ruby编程语言全景解析:从基础到进阶

Ruby是一种动态的、面向对象的编程语言&#xff0c;以其优雅的语法和强大的功能而闻名于世。自从1995年由日本程序员松本行弘&#xff08;Yukihiro Matsumoto&#xff09;发布以来&#xff0c;Ruby便迅速成为了开发者中颇受欢迎的编程语言之一。无论是构建简单的脚本还是复杂的…

数据结构的时间复杂度和空间复杂度

目录 时间复杂度 空间复杂度 时间复杂度 基本操作的执行次数&#xff0c;为时间复杂度。 我们使用大O的渐进表示法来表示时间复杂度。 怎么使用&#xff1f; 先看例子&#xff1a; 在这个例子中&#xff0c; 基本操作为变量 count 的 加加 操作&#xff0c;并且&#xff0c;执行…

Ubuntu20.04 解决一段时间后键盘卡死 输入延迟很大的问题 ubuntu

Ubuntu20.04 解决一段时间后键盘卡死 输入延迟很大的问题 为了确保您能顺利通过双击快捷方式来重启 IBus&#xff0c;下面详细描述了从脚本创建到快捷方式设置的每一步&#xff0c;包括具体的命令行操作和必要的说明&#xff0c;以确保您能够按步骤成功执行。 步骤 1: 创建并…

解决Oracle DECODE函数字符串截断问题的深度剖析20241113

解决Oracle DECODE函数字符串截断问题的深度剖析 在使用Oracle数据库进行开发时&#xff0c;开发者可能会遇到一些令人困惑的问题。其中&#xff0c;在使用DECODE函数时&#xff0c;返回的字符串被截断就是一个典型的案例。本文将以学生管理系统为背景&#xff0c;深入探讨这个…

【Chapter 3】Machine Learning Classification Case_Prediction of diabetes-XGBoost

文章目录 1、XGBoost Algorithm2、Comparison of algorithm implementation between Python code and Sentosa_DSML community edition(1) Data reading and statistical analysis(2)Data preprocessing(3)Model Training and Evaluation(4)Model visualization 3、summarize 1…

Rust Struct 属性初始化

结构体是用户定义的数据类型&#xff0c;其中包含定义特定实例的字段。结构有助于实现更容易理解的抽象概念。本文介绍几种初始化结构体对象的方法&#xff0c;包括常规方法、Default特征、第三方包实现以及构建器模式。 Struct声明与初始化 struct Employee {id: i32,name: …

AI大模型微调:Qwen2大模型微调入门实战(完整代码)

简介&#xff1a; 该教程介绍了如何使用Qwen2&#xff0c;一个由阿里云通义实验室研发的开源大语言模型&#xff0c;进行指令微调以实现文本分类。微调是通过在&#xff08;指令&#xff0c;输出&#xff09;数据集上训练来改善LLMs理解人类指令的能力。教程中&#xff0c;使用…

树莓派(Raspberry Pi)Pico 2 C_C++开发环境配置(Docker+SDK)

树莓派&#xff08;Raspberry Pi&#xff09;Pico 2 C_C开发环境配置&#xff08;DockerSDK&#xff09; 开发环境容器系统环境配置配置 Raspberry Pi Pico 2 C/C 开发环境编译构建 Blink 示例程序下载 pico-sdk 和 pico-examples构建 Blink 链接 文章介绍了在容器中配置Raspbe…