【计算机网络】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.rhkb.cn/news/471033.html

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

相关文章

Linux git-bash配置

参考资料 命令提示符Windows下的Git Bash配置&#xff0c;提升你的终端操作体验WindowsTerminal添加git-bash 目录 一. git-bash配置1.1 解决中文乱码1.2 修改命令提示符 二. WindowsTerminal配置git-bash2.1 添加git-bash到WindowsTerminal2.2 解决删除时窗口闪烁问题 三. VS…

【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

关键词&#xff1a;一多、响应式、媒体查询、栅格布局、断点、UI 随着设备形态的逐渐增多&#xff0c;应用界面适配也面临着很大问题&#xff0c;在以往的安卓应用开发过程中&#xff0c;往往需要重新开发一套适用于大屏展示的应用&#xff0c;耗时又耗力&#xff0c;而鸿蒙提供…

向日葵软件Windows系统连接苹果系统(MacOS)的无反应问题解决办法

前言 向日葵软件最近开始收费了的&#xff0c;打算收割我们。这也是没有办法的事情&#xff0c;毕竟他们的程序员也是需要吃饭的&#xff0c;我也表示理解。 所以&#xff0c;我在连接了几次发现反应很迟钝后&#xff0c;果断的买了158元的包年会员。 但是&#xff0c;在买了会…

neo4j desktop基本入门

下载安装不在赘述&#xff0c;本文只记述一些neo4j的基本入门操作 连接本地neo4j数据库 1. 点击ADD添加连接 端口一般是7687 账户名和密码忘记了&#xff0c;可以通过neo4j web&#xff08;默认为neo4jneo4j://localhost:7687/neo4j - Neo4j Browser&#xff09;重置密码 AL…

编写红绿起爆线指标(附带源码下载)

编写需求&#xff1a; 想问问有没有能标注行情起爆点的指标。 效果展示&#xff1a; 红线上&#xff0c;出现绿柱转红柱做多。 蓝线下&#xff0c;出现红柱转绿柱做空。 源码展示&#xff08;部分源码&#xff0c;完整源码需下载源码文件&#xff09;&#xff1a; IsMainIn…

ubuntu20.04 解决Pytorch默认安装CPU版本的问题

ubuntu20.04 解决Pytorch默认安装CPU版本的问题 在使用Anaconda安装支持CUDA的PyTorch版本时&#xff0c;遇到只能安装CPU版本的PyTorch是一个常见问题。这通常由于Anaconda环境配置、镜像源设置不当或版本匹配问题导致。以下是详尽的解决方案和步骤&#xff0c;以确保能够正确…

C++《继承》

在之前学习学习C类和对象时我们就初步了解到了C当中有三大特性&#xff0c;分别是封装、继承、多态&#xff0c;通过之前的学习我们已经了解了C的封装特性&#xff0c;那么接下来我们将继续学习另外的两大特性&#xff0c;在此将分为两个章节来分别讲解继承和多态。本篇就先来学…

数字孪生在智慧能源项目中的关键作用,你了解多少?

随着能源行业不断向智能化、数字化转型&#xff0c;数字孪生技术在智慧能源项目中扮演的角色愈发重要。数字孪生不仅带来了前所未有的资源优化和成本节约方式&#xff0c;还为整个能源系统的可持续运营奠定了坚实基础。那么&#xff0c;为什么数字孪生技术在智慧能源项目中如此…

Window下PHP安装最新sg11(php5.3-php8.3)

链接: https://pan.baidu.com/s/10yyqTJdwH_oQJnQtWcwIeA 提取码: qz8y 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 (链接失效联系L88467872) 1.下载后解压文件&#xff0c;将对应版本的ixed.xx.win文件放进php对应的ext目录下&#xff0c;如图所示 2.修改ph…

Postman上传图片如何处理

打开Postman&#xff0c;创建一个新的请求 URL: http://90.104.232.49:80/dev-api/appcommon/upload 如果有解密进入上传就在请求头添加 点击“Body”选项卡。 选择“form-data”类型。 在“KEY”列中输入文件字段的名称&#xff0c;例如file。 在“VALUE”列中&#xff0…

陪诊问诊APP开发实战:基于互联网医院系统源码的搭建详解

时下&#xff0c;开发一款功能全面、用户体验良好的陪诊问诊APP成为了医疗行业的一大热点。本文将结合互联网医院系统源码&#xff0c;详细解析陪诊问诊APP的开发过程&#xff0c;为开发者提供实用的开发方案与技术指导。 一、陪诊问诊APP的背景与功能需求 陪诊问诊APP核心目…

Leecode热题100-35.搜索插入位置

给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2示例 2: 输入:…

Axure设计之文本编辑器制作教程

文本编辑器是一个功能强大的工具&#xff0c;允许用户在图形界面中创建和编辑文本的格式和布局&#xff0c;如字体样式、大小、颜色、对齐方式等&#xff0c;在Web端实际项目中&#xff0c;文本编辑器的使用非常频繁。以下是在Axure中模拟web端富文本编辑器&#xff0c;来制作文…

【MySQL 保姆级教学】事务的隔离级别(详细)--下(13)

事务的隔离级别 1. 如何理解事务的隔离性2. 事务隔离级别的分类3. 查看和设置事务隔离级别3.1 全局和会话隔离级别3.2 查看和设置隔离级别 4. 事务隔离级别的演示4.1 读未提交&#xff08;Read Uncommitted&#xff09;4.2 读已提交&#xff08;Read Committed&#xff09;4.3 …

大厂的 404 页面都长啥样?看看你都见过吗~~~

当我们浏览网页时&#xff0c;不小心走错路径或打开一个已被移除的页面时&#xff0c;常会遇到“404页面”。这时&#xff0c;普通网站往往只会显示冷冰冰的“404 Not Found”&#xff0c;但大厂们却能把404页面玩出花来。国内互联网大厂的404页面不仅独特&#xff0c;而且设计…

acwing算法基础02一高精度,前缀和,差分

#include <iostream> #include <vector> using namespace std;const int N 1e6 10; //模板 CABvector<int> add(vector<int> &A,vector <int> &B) {vector<int> C;int t 0; // 用来保存每位的和&#xff08;包括进位&#xff…

WebAssembly在现代Web开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 WebAssembly在现代Web开发中的应用 WebAssembly在现代Web开发中的应用 WebAssembly在现代Web开发中的应用 引言 WebAssembly 概述…

06.VSCODE:备战大项目,CMake专项配置

娇小灵活的简捷配置不过是年轻人谈情说爱的玩具&#xff0c;帝国大厦的构建&#xff0c;终归要交给CMake去母仪天下。一个没有使用 CMake 的 C 项目&#xff0c;就像未来世界里的一台相声表演&#xff0c;有了德纲却无谦&#xff0c;观众笑着遗憾。—— 语出《双城记》作者&…

从社交媒体到元宇宙:Facebook未来发展新方向

Facebook&#xff0c;作为全球最大的社交媒体平台之一&#xff0c;已经从最初的简单互动工具发展成为一个跨越多个领域的科技巨头。无论是连接人与人之间的社交纽带&#xff0c;还是利用大数据、人工智能等技术为用户提供个性化的体验&#xff0c;Facebook一直引领着社交网络的…

【go从零单排】JSON序列化和反序列化

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在 Go 语言中&#xff0c;处理 JSON 数据主要依赖于 encoding/json 包。这个包提…