【网络】UDP协议的简单使用

目录

服务器

客户端

测试

code for Udp_echo_serve

Udp_dict_serve


UDP是基于socket(基于IP和port进行通信就叫做socket通信)进行网络通信的,那我们这篇博客就来介绍一下基于UDP通信的基本流程,先让服务端和客户端进行简单的跨网络通信。

服务器

首先我们需要创建UDP套接字,用到的接口是

man socket

如果要使用UDP通信,第一个参数就传

它用来表示基于网络通信,第二个参数就传

它用来表示是面向数据报,第三个参数我们就默认传0就可以了,因为前两个参数就可以确定它就是UDP协议。它的返回值我们可以认为是一个文件描述符,未来我们就可以向这个文件中去写入或读取东西

接下来是bind socket和网络信息

man 2 bind

第一个参数就是前面接口的返回值,第二个参数是输入性参数,是一个结构体的指针,所以我们要创建这样一个结构体并且填充内容,第三个参数就是第二个参数的大小

所以在绑定之前,我们需要创建struct sockaddr的对象并且填充内容:

因为socket编程是有不同种类的,而操作系统又是拿C语言写的,为了统一接口,我们就用struct sockaddr这个类型,具体到网络通信是struct sockaddr_in这个类型,所以我们创建的是struct sockaddr_in这个类型的变量,到时候进行强制类型转换成struct sockaddr类型

local的类型是一个结构体,结构体中有这些类型:

我们可以看到这里面有port,就是我们传进来的端口号,这个端口号当然也要进行网络传输,因为放到网络中的数据必须是大端,所以我们有接口用来主机序列转网络序列

有了这些接口,我们就可以任意的16位,32位,主机序列转网络序列,网络序列转主机序列。

传完了端口号,就要传ip地址了,就是sin_addr的内容,同样这个也需要主机序列转网络序列,但同时我们知道从命令行参数传进来的IP地址是字符串风格的点分十进制的格式(比如193.168.111.222,这样占15个字节),这样占的空间就大,我们知道每一位都是0~255,这用一个字节来表示整数足够了(这样只占四个字节),所以我们要将字符串风格的点分十进制转换成4字节IP。上面两个工作可以通过下面的接口全部完成

man inet_addr

填充完了我们就可以进行bind了,到此初始化的工作就完成了

下面就是不断的从网络中获取信息,我们可以设置成死循环的形式,我们先实现这样的场景,谁给我们发的,我们再发回去

UDP是面向数据报的,从网络中获取信息的接口是:

man recvfrom

第二个参数是要把从网络中获得的信息存到哪,后两个参数是输出型参数,里面就存放着这个消息是谁发来的一些信息

我们再把消息发回去的接口是:

man sendto

后两个参数就存放着要把消息发送给谁

这样,服务器大致就写好了,还有一些细节需要处理

我们运行主函数的代码时命令行参数就要写上ip和端口号

客户端

客户端要运行主函数肯定是要加上你想访问的服务器的ip地址和端口号,因为这样可以在互联网中唯一确定一个进程,客户端和服务器一样,也是要创建socket,但是不用显示bind,就是我们不要bind,客户端第一次向服务器发消息的时候操作系统会自动bind,因为如果客户端显示的bind,那就意味着不同的客户端可能用一个端口号(比如手机中的抖音和淘宝用一个端口号),这样就导致两个客户端无法同时启动,就会出现端口号冲突的问题。那么就意味着客户端的代码要比服务器要好写

测试

我们像下面这样运行服务器

它是可以成功的,127.0.0.1这个IP我们称为本地环回,它不将服务发送到网络中,可以用于本地通信,常用于代码测试,于是此时我们再起一个SSH渠道就可以实现本地的服务器和客户端通信了

这是本地环回,毕竟不是跨网络的,我们把IP换成服务器的公网IP试一试

可以看到它会报错,因为我们的服务器,无法直接bind公网IP(云服务器不允许),我们也严重不推荐绑定任意一个确定的IP(虚拟机可以)

因为一台设备可能有多个IP地址,我向每个IP地址发,进程都应该收到,如果bind特定的IP地址,那么只有这个IP地址可以收到,所以我们一般传0.0.0.0,简写成0,表示任意IP地址bind,所以之前的代码中还是不要传IP了,因为确定是0

这样,客户端给本地环回和公网IP就都可以发消息了

网络命令

还有一些网络命令我们补充一下:

ping 用来检测网络连通性,加上-c3(count=3)表示检测三次

netstat -puan 用来查udp网络服务

p代表process进程,u代表udp,a代表all,n代表number,就是能显示成数字的都显示成数字

同样,我们要查tcp网络服务是netstat -tlnp

t就表示tcp,l表示状态是listen的

watch -n 1 ls表示每个一秒执行一次ls命令,我们就可以用它来查网络服务

我们之前要查一个进程的pid要这样:

ps ajx | head -1 && ps ajx | grep server非常繁琐,于是我们可以用

pidof server就可以直接查到进程的pid

我们如果想通过pid杀掉进程就可以

pidof server | xargs kill -9

这里的xargs就是把管道中的东西放到-9后面

code for Udp_echo_serve

//UdpServer.hpp#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cerrno>
#include<cstdlib>
#include <cstring>
#include "Log.hpp"enum error
{SOCKET_ERR = 1,BIND_ERR,USAGE_ERR,};
class UdpServer
{
public:UdpServer(uint16_t port) : _port(port), _socketfd(-1){}void InitServer(){// 1.创建UDP socket套接字_socketfd = socket(AF_INET, SOCK_DGRAM, 0);if (_socketfd < 0){LOG(FATAL, "socket error,%d,%s", errno, strerror(errno));exit(SOCKET_ERR);}LOG(INFO, "create socket success,socket:%d", _socketfd);// 填充struct sockaddr_in结构struct sockaddr_in local;bzero(&local, sizeof(local)); // 对空间进行清0local.sin_family = AF_INET;local.sin_port = htons(_port);local.sin_addr.s_addr=INADDR_ANY;//这个数就是0,因为是0,大小端也就没意义了// local.sin_addr.s_addr = inet_addr(_ip.c_str());int n = bind(_socketfd, (struct sockaddr *)&local, sizeof(local));if (n < 0){LOG(FATAL, "bind error,%d,%s", errno, strerror(errno));exit(BIND_ERR);}LOG(INFO, "bind success");}void start(){while (true){char buffer[1024];struct sockaddr_in peer;socklen_t len=sizeof(peer);ssize_t n=recvfrom(_socketfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);if(n>0){buffer[n]=0;LOG(DEBUG,"get message from[%s,%d]:%s",inet_ntoa(peer.sin_addr),ntohs(peer.sin_port),buffer);//这样解析就知道是谁发过来的sendto(_socketfd,buffer,strlen(buffer),0,(struct sockaddr*)&peer,len);}}}private:int _socketfd;// std::string _ip;uint16_t _port;
};
//Main.cc#include<iostream>
#include"UdpServer.hpp"
void Usage(char* arg)
{std::cout<<"Usage:  please enter:"<<std::endl;std::cout<<arg<<' '<<"server port"<<std::endl;
}
int main(int argc,char*argv[])
{if(argc!=2){Usage(argv[0]);exit(USAGE_ERR);}Enablescreen();uint16_t port=std::stoi(argv[1]);UdpServer udps(port);udps.InitServer();udps.start();return 0;
}
//UdpClient.cc#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
void Usage(char *arg)
{std::cout << "Usage:  please enter:" << std::endl;std::cout << arg << ' ' << "server ip " << "server port" << std::endl;
}
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);//创建socket套接字int socketfd = socket(AF_INET, SOCK_DGRAM, 0);if (socketfd < 0){std::cerr << "socket error" << std::endl;}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());std::string message;while(true){std::cout<<"Please Enter# ";std::getline(std::cin,message);sendto(socketfd,message.c_str(),message.size(),0,(struct sockaddr*)&server,sizeof(server));//给服务器发消息struct sockaddr_in peer;socklen_t len=sizeof(peer);char buffer[1024];ssize_t n=recvfrom(socketfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);//接收来自服务器的消息if(n>0){buffer[n]=0;std::cout<<"server echo# "<<buffer<<std::endl;}}return 0;
}

Udp_dict_serve

上面我们已经会了实现服务器和客户端之间的一个基本跨网络通信,下面我们可以给服务器部署一些任务,就比如查字典的服务:客户端通过发送一些英文单词给服务器,然后从服务器中获得汉语翻译,于是我们就在上面的代码上简单写一个Dict.hpp来实现这个功能

#include <iostream>
#include <string>
#include <unordered_map>
#include "Log.hpp"const std::string defaultconfpath = "./Dict.txt";
const std::string seq = ": ";class Dict_serve
{
private:bool Load(){std::ifstream in(_conf_filepath);if (!in.is_open()){LOG(FATAL, "open %s error", _conf_filepath.c_str());return false;}std::string line;while (std::getline(in, line)){if (line.empty())continue;auto pos = line.find(seq);if (pos == std::string::npos)continue;std::string word = line.substr(0, pos);if (word.empty())continue;std::string han = line.substr(pos + seq.size());if (han.empty())continue;LOG(DEBUG, "load %s %s success", word.c_str(), han.c_str());_dict.insert({word, han});}in.close();LOG(DEBUG, "load %s success", _conf_filepath.c_str());return true;}public:Dict_serve(const std::string &path = defaultconfpath) : _conf_filepath(path){Load();}std::string translate(const std::string &word){auto iter = _dict.find(word);if (iter == _dict.end())return "nofind(未找到)";// return _dict[word];return iter->second;}private:std::unordered_map<std::string, std::string> _dict;std::string _conf_filepath;
};

所有的服务器本质还是解决的是输入输出的问题,我们不想让网络通信模块和翻译(业务)模块强耦合,所以可以这样做:

把一个通用的任务当作udpserver的成员变量,以后就通过这个变量做任务

所以我们在构建服务器对象时这样去构建:

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

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

相关文章

深入探索Unity协程:揭开CSharp迭代器背后的神秘面纱

协程是一种特殊类型的迭代器方法&#xff0c;允许你在多个帧之间分段执行代码。可以用来处理时间延迟、异步操作和顺序执行的任务&#xff0c;而不阻塞主线程。Unity协程的实现依赖于C#语言提供的迭代器相关的语言特性&#xff0c;所以想要弄清楚Unity协程的底层原理&#xff0…

单例的饿汉式,懒汉式的线程安全问题

1 单例的饿汉式 对象在类加载的时候就创建了&#xff0c;线程安全&#xff0c;速度块&#xff0c;但是浪费空间&#xff0c; public class Hungry {//唯一对象private static final Hungry HUNGRY new Hungry();byte byte1[]new byte[1024];byte byte2[]new byte[1024];byte…

Java的时间复杂度和空间复杂度和常见排序

目录 一丶时间复杂度 二丶空间复杂度 三丶Java常见排序 1. 冒泡排序&#xff08;Bubble Sort&#xff09; 2.插入排序&#xff08;Insertion Sort&#xff09; 3.希尔排序&#xff08;Shell Sort&#xff09; 4.选择排序&#xff08;Selection Sort&#xff09; 5.堆排序&am…

qmt量化交易策略小白学习笔记第61期【qmt编程之期权行情数据--get_market_data_ex函数】

qmt编程之获取期权数据 期权行情数据 qmt更加详细的教程方法&#xff0c;会持续慢慢梳理。 也可找寻博主的历史文章&#xff0c;搜索关键词查看解决方案 &#xff01; 获取期权行情数据 获取期权最新数据&#xff0c;首先需要进行数据订阅。完成合约订阅后&#xff0c;用g…

【OpenCV】灰度化处理

文章目录 1. 图像灰度化处理对比2. 代码示例3. 二值化处理 1. 图像灰度化处理对比 2. 代码示例 #include <opencv2/opencv.hpp> using namespace cv;int main() {Mat currentImage imread("path_to_image.jpg"); // 读取彩色图像Mat grayImage;// 将彩色图像…

Rust的常数、作用域与所有权

【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学&#xff0c;之一 -CSDN博客 Rust到底值不值得学&#xff0c;之二-CSDN博客 Rust的数据类型-CSDN博客 3.7 常…

HTTP 二、进阶

四、安全 1、TLS是什么 &#xff08;1&#xff09;为什么要有HTTPS ​ 简单的回答是“因为 HTTP 不安全”。由于 HTTP 天生“明文”的特点&#xff0c;整个传输过程完全透明&#xff0c;任何人都能够在链路中截获、修改或者伪造请求 / 响应报文&#xff0c;数据不具有可…

阿里不认命

​ 转载&#xff1a;新熵 原创 作者丨萧维 编辑丨影蕨 国家定调了&#xff01;一系列积极信号为平台经济注入一剂强心针&#xff0c;阿里迎来新生。 最近&#xff0c;阿里捷报频传&#xff01; 先是8月28日&#xff0c;阿里巴巴完成香港双重主要上市。紧接着&#xff0c;8月…

基于聚类与LSTM对比特币价格深度分析与预测

1.项目背景 比特币作为全球最具影响力的加密货币之一&#xff0c;其价格受到多种复杂因素的共同作用&#xff0c;包括市场情绪、政策变化、大型机构的投资行为等&#xff0c;这些因素在不同的市场阶段对比特币价格波动产生直接或间接的影响。通过对比特币市场的深入分析&#…

66城代表齐聚!蓝卓分享“全国经验”,批量复制推动中小企业数字化转型

9月6日下午&#xff0c;2024中小企业数字化转型现场交流活动在浙江宁波隆重举行。 全国66个中小企业试点城市500多名中小企业主管部门及专家学者&#xff0c;制造业企业、数字化转型服务商等重点企业代表齐聚宁波&#xff0c;共同探讨中小企业数字化转型的模式和路径。 工业和…

酒店智能轻触开关:智慧化的创新实践

在追求高品质住宿体验的今天&#xff0c;酒店智能轻触开关作为智慧酒店建设的关键一环&#xff0c;正逐步成为提升酒店服务品质、优化运营效率、增强顾客满意度的有力工具。本文将深入探讨酒店智能轻触开关如何助力酒店实现智慧化管理&#xff0c;以及它所带来的多重变革。 一、…

VSCode连接docker

1.启动ssh服务 vim /root/.bashrc 或者 vim ~/.bashrc /usr/sbin/sshd #启动ssh服务~代表主目录&#xff0c;cd ~会返回root目录 cd / 返回最根上的目录 为了防止每次打开容器都要输入此指令&#xff0c;我们直接在 ~/.bashrc文件最后一行添加sshd启动命令即可。 打开终端…

【JAVA开源】基于Vue和SpringBoot的图书个性化推荐系统

本文项目编号 T 015 &#xff0c;文末自助获取源码 \color{red}{T015&#xff0c;文末自助获取源码} T015&#xff0c;文末自助获取源码 目录 一、系统介绍1.1 业务分析1.2 用例设计1.3 时序设计 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究…

掌握ChatGPT写论文六步提问法,会提问才能写出优质好论文

大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾学术科研AI实操的学术人。关于使用ChatGPT等AI学术科研的相关问题都可以分享,相互成就,共同进步,为大家带来最酷最有效的智能AI学术科研写作攻略。 今天给大家分享的是借助GPT一年发两篇SCI的学术大拿总结的ChatGPT六…

IPS和IDS有啥区别?

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330&scene21#wechat_redirect 《网安面试指南》…

ChatGPT付费创作系统V3.0.6独立版 WEB+H5+小程序端 (新增AI全网搜索+文档解析+豆包AI通道)安装部署教程

播播资源GPT付费体验系统最新版系统是一款基于ThinkPHP框架开发的AI问答小程序&#xff0c;是基于国外很火的ChatGPT进行开发的Ai智能问答小程序。这是一种基于人工智能技术的问答系统&#xff0c;可以实现智能回答用户提出的问题。相比传统的问答系统&#xff0c;ChatGPT可以更…

认识Linux及Linux的环境搭建

目录 1、什么是Linux2、Linux环境搭建2.1 下载安装 Xshell2.2 下载安装 VMware Workstation Pro2.3 选择适合自己系统 1、什么是Linux Linux&#xff0c;一般指GNU/Linux&#xff08;单独的Linux内核并不可直接使用&#xff0c;一般搭配GNU套件&#xff0c;故得此称呼&#xff…

ARM基础知识---CPU---处理器

目录 一、ARM架构 1.1.RAM---随机存储器 1.2.ROM---只读存储器 1.3.flash---闪存存储器 1.4.时钟&#xff08;振晶&#xff09; 1.5.复位 二、CPU---ARM920T 2.1.R0~R12---通用寄存器 2.2.PC程序计数器 2.3.LR连接寄存器 2.4.SP栈指针寄存器 2.5.CPSR当前程序状态寄存…

java,php,go,nodejs,Python开发web项目优缺点对比

Java 优点:java 是一门广泛应用于企业级开发的语言,丰富且庞大的开发框架和库。有较高的性能和可伸缩性。生态系统庞大且成熟,拥有大量的开源框架和工具,可以加速开发过程。 内置对多线程的支持,适合处理高并发的 Web 项目。 缺点:相比其他语言,Java 的语法相对冗长繁琐…

【H2O2|全栈】关于Photoshop | PS(4)

PS的一些杂谈&#xff08;亖&#xff09; 目录 PS的一些杂谈&#xff08;亖&#xff09; 前言 准备工作 图形工具 基本属性 混合选项 形状图层 文字工具 基本属性 进一步变化文字 组和图层 UI设计案例 预告和回顾 后话 前言 这一篇博客我将会写一下图形工具和…