udp网络通信 socket

套接字是实现进程间通信的编程。IP可以标定主机在全网的唯一性,端口可以标定进程在主机的唯一性,那么socket通过IP+端口号就可以让两个在全网唯一标定的进程进行通信。

套接字有三种:

域间套接字:实现主机内部的进程通信的编程

原始套接字:使用网络层或者数据链路层的接口进行编程,更难更底层,例如制作抓包等网络工具

网络套接字:实现用户通信的编程

udp网络通信

服务端server

分析:

服务端最少需要有两个接口,一个用来初始化服务器,一个用来运行服务器

一:初始化服务器接口

创建socket,绑定端口

1.创建socket

socket接口

fedd87d5c4ed451a98cd741758e1fd65.png

第一个参数是域,用来确定通信类型27575ae93e4e46ccb56a96cff6bdffbb.png 

AF_UNIX就是域间套接字,AF_INET/AF_INET6是IPv4/IPv6的网络套接字

第二个参数是传输的数据种类 

1885a033313f4789a12b066d2b3a3cf2.png

最常用的是前两个,SOCK_STREAM是面向字节流(TCP),SOCK_DGRAM是面向数据报(UDP)

第三个参数传0即可,这里用不到 

0ddec27613af48f6ad4685f1ac6a541c.png

返回值返回一个文件描述符 

2.绑定端口

bind接口

1dac49aa4920483c96a1505b8fcbfff7.png

第一个参数是socket返回的文件描述符

第二个参数是一个包含通信属性的结构体,例如通信域,ip地址和端口号。这是一个输出型参数,而且不同的通信类型的结构体不一样,传参时要进行类型转换。

47ab09aafd6d47729a411520d3c0fba1.png

c84c77ee04cf4e0b821d436be4789ae2.png

sockaddr_in有三个成员需要我们初始化:
1.sin_family:通信域,网络通信使用AF_INET

这个成员使用了宏函数,宏传入参数sin_,所以sa_prefix##family等价于sin_family,它是一个无符号短整型

2.sin_port:端口号 

端口号会在网络间传输,需要对我们传入的端口号进行处理,使其符合网络字节序,要使用htons()接口

3.sin_addr:ip地址

这个成员是一个结构体,结构体内有一个无符号整形的成员。但是我们一般的ip地址是一个字符串例如(192.168.33.131),所以我们要先将字符串转化为数字,再将数字变为网络字节序。这要用到inet_addr(char*)接口

第三个参数时结构体大小,直接计算即可

注意:一般服务器bind的ip地址是0.0.0.0,如果一个服务是绑定到 0.0.0.0 ,那么外部机器访问该机器上所有 IP 都可以访问该服务。如果服务绑定到的是特定的 ip,则只有访问该 ip 才能访问到服务。

 初始化服务器代码样例:

class udpserver{
public:void init(){// 创建udp serversockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){exit(1);}// bind socked//初始化结构体struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(port_);                  // 转化成网络字节序local.sin_addr.s_addr = inet_addr(ip_.c_str()); // 将ip转化成数字,再将数字转化为网络字节序//bindif (bind(sockfd_, (struct sockaddr *)&local, sizeof(local)) < 0){exit(2);}}udpserver(uint16_t port = 8080, string ip = "0.0.0.0"): port_(port), ip_(ip){}~udpserver(){if (sockfd_ > 0)close(sockfd_);}
private:int sockfd_;uint16_t port_;string ip_;
};

二:运行服务器接口

接收数据,对数据做处理,最后发送数据

1.接收数据

recvfrom接口

c0a1d65b28404ddba7faec9ae3462b78.png

90acb0527a354fff915010617d47967d.png

第一个参数是socket返回的文件描述符,第二个是接收的数据存放的位置,第三个参数是buf空间的大小,第四个参数在本文中这里只要传0即可满足需求。

第五个参数是用来存储数据发送方(客户端)属性的结构体,第六个参数是结构体大小的指针

为什么要记录客户端的通信属性呢?因为服务端在对数据做处理后还要发送回客户端。 

 2.对数据做处理

需要根据实际需求进行处理,可以通过传函数指针,实现代码分层。见后面的代码示例。

3.发送数据

sendto接口

a2a60ee6474c46c883e5e79d428a34a5.png

5faa90bb08204028a1a991b756f61956.png

 第一个参数是socket的文件描述符,第二个参数是要发送的数据的地址,第三个参数是发送数据的大小,第四个参数传0。

第五个参数是数据接收方(客户端)属性的结构体,第六个参数是结构体大小。

运行服务器代码样例(包括前面的代码):

//udpserver.hpp
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
using func = function<string(char*)>;
class udpserver{
public:void init(){// 创建udp serversockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd_ < 0){exit(1);}// bind socked//初始化结构体struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(port_);                  // 转化成网络字节序local.sin_addr.s_addr = inet_addr(ip_.c_str()); // 将ip转化成数字,再将数字转化为网络字节序//bindif (bind(sockfd_, (struct sockaddr *)&local, sizeof(local)) < 0){exit(2);}}void run(func fun){char buf[1024] = {0};while (1){struct sockaddr_in client; // 客户端的信息socklen_t len = sizeof(client);// 收数据ssize_t n = recvfrom(sockfd_, buf, sizeof(buf), 0, (struct sockaddr *)&client, &len);if (n < 0){cout << "receice fail" << endl;continue;}buf[n] = 0;cout << "server get:" << buf << endl;// 处理数据,通过传递的函数实现数据处理的和网络通信解耦string ret = fun(buf);// 发送数据n = sendto(sockfd_, ret.c_str(), ret.size(), 0, (struct sockaddr *)&client, len);}}udpserver(uint16_t port = 8080, string ip = "0,0,0,0"): port_(port), ip_(ip){}~udpserver(){if (sockfd_ > 0)close(sockfd_);}
private:int sockfd_;uint16_t port_;string ip_;
};//main.cpp
#include"udpserver.hpp"
#include<memory>using namespace std;
string datagram(char* data)
{string ret = "Get message:";ret += data;return ret;
}
int main()
{unique_ptr<udpserver> server(new udpserver());server->init();server->run(datagram);return 0;
}

客户端client

分析:

客户端需要初始化客户端,发送数据,接收数据

一:初始化客户端

创建socket和服务端一样,不同的是客户端的bind是操作系统完成的不需要我们操作,客户端会在发送数据时由OS随机bind一个端口。因为客户端的设备可能同时请求多个服务端,例如手机会同时运行很多app,客户端的程序很难为服务端留一个固定的端口(不同公司之间开发软件不可能商量谁要用哪个客户端的端口),而且服务端没必要第一时间知道客户端的端口,客户端发送数据请求时可以获取到客户端的属性

二:发送数据

使用sendto()接口,和服务端一样。

三:接收数据

使用recvfrom()接口,和服务端一样。

客户端代码样例:

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>using namespace std;
int main(int argc, char *argv[])
{//获取命令行参数,ip和端口号if(argc != 3){cout << "Please input in this way" << endl;cout << "./udpclient" << " [ip]" << " [port]" << endl;}string ip = argv[1];uint16_t port = stoi(argv[2]);// 创建socketint sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (sockfd < 0){cout << "client create fail" << endl;}//客户端不需要bind,但是客户端会在发送数据时由OS随机bind一个端口,因为客户端设备同时请求多个服务端,服务端很难让客户端的程序为其留一个固定的端口,而且没必要第一时间知道客户端的端口,客户端发送数据请求时可以获取到// 创建服务端信息的结构体struct sockaddr_in server;server.sin_port = htons(port);server.sin_family = AF_INET;server.sin_addr.s_addr = inet_addr(ip.c_str());socklen_t len = sizeof(server);char buf[1024] = {0};string message;while (1){// 发送数据cout << "Please Enter@";getline(cin, message);sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&server, len);// 接收数据struct sockaddr_in tem;socklen_t len_tem = sizeof(tem);ssize_t n = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&tem, &len);if (n < 0){cout << "client receive fail" << endl;continue;}buf[n] = 0;cout << buf << endl;}
}

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

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

相关文章

Kettle发送邮件功能如何配置以实现自动化?

kettle发送邮件如何设置&#xff1f;Kettle配置发送邮件的方法&#xff1f; Kettle发送邮件功能能够帮助用户在数据处理过程中自动发送电子邮件&#xff0c;极大地提高了工作效率。AokSend将详细介绍如何配置Kettle发送邮件功能&#xff0c;以实现自动化操作。 Kettle发送邮件…

C++笔记19•数据结构:红黑树(RBTree)•

红黑树 1.简介&#xff1a; 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路 径会比其他路径长出俩倍…

使用百度飞桨PaddleOCR进行OCR识别

1、代码及文档 代码&#xff1a;https://github.com/PaddlePaddle/PaddleOCR?tabreadme-ov-file 介绍文档&#xff1a;https://paddlepaddle.github.io/PaddleOCR/ppocr/overview.html 2、依赖安装 在使用过程中需要安装库&#xff0c;可以依据代码运行过程中的提示安装。…

MySQL Email验证流程详解:从注册到激活!

MySQL Email通知系统搭建教程&#xff01;如何从MySQL发送邮件&#xff1f; MySQL Email验证是一个至关重要的环节&#xff0c;它确保了用户注册过程的安全性和有效性。AokSend将详细介绍从用户注册到MySQL Email激活的完整流程&#xff0c;帮助开发者更好地理解和实现这一功能…

视频编码与传输 学习笔记 1 一些视频压缩算法的介绍

大概是这么个结构&#xff1a; 说白了&#xff0c;就是视频太大&#xff0c;不压缩不行&#xff0c;因此我们会用压缩比非常夸张但对于视频来说效果很好的压缩方法先对视频压缩&#xff08;source coding&#xff09;然后把压缩后的视频发出去&#xff0c;要看的时候再解压。 就…

青岛实训 8月22号 day34

一、回顾 1.主从复制&#xff08;高可用&#xff09; 2.传统的主从复制 3.gtids事务型的主从复制 4.注意 1&#xff09;server_id唯一 2&#xff09;8.X版本需要get_ssl_pub_key 3&#xff09;5.X不需要 4&#xff09;change master to 5&#xff09;stop | start slave 5.非…

HIVE 数据仓库工具之第二部分(数据库相关操作)

HIVE 数据仓库工具之第二部分&#xff08;数据库相关操作&#xff09; 一、Hive 对数据库的操作1.1 创建数据库1.1.1 创建数据库语法1.1.3 示例 1.2 使用数据库1.2.1 使用数据库语法1.2.2 示例 1.3 修改数据库1.3.1 修改数据库的语法1.3.2 示例 1.4 删除数据库1.4.1 删除数据库…

Aloudata CAN 发布:真正实现企业指标的管理、研发与消费一体化

对于企业的运营和管理来说&#xff0c;集自动化数据生产、业务化数据语言、智能化数据分析的指标管理方案至关重要。 指标是对业务过程和结果的度量&#xff0c;正如德鲁克所说&#xff0c;“如果无法度量就无法管理”。 指标管理痛点爆发&#xff0c;管、研、用一体方案备受青…

python-简单的dos攻击

前言 这个是DOS攻击学习(注意&#xff1a;千万别去攻击有商业价值的服务器或应用&#xff0c;不然会死的很惨(只有一个IP通过公网访问容易被抓),前提是网站没有攻击防御) 创建一个以python编写的后端web服务(好观察) 安装flask pip install flask from flask import Flaskapp …

Day22_K8S

文章目录 3.资源管理方式通过命令管理通过配置文件管理4. 基本概念入门4.1 Namespace4.2 Pod4.3 Label4.4 Deployment4.5 Service5. Pod详解5.1 Pod介绍5.2 Pod配置5.3 Pod生命周期5.3.1 初始化容器5.3.2 钩子函数5.3.3 容器探测5.3.4 重启策略5.4 Pod调度5.4.1 定向调度5.4.2 …

JavaScript DOM事件流之捕获与冒泡

DOM事件流——捕获与冒泡 网页是由一个一个元素组成的&#xff0c;正如我们肉眼所见&#xff0c;网页上的元素存在包含关系&#xff0c;简单的点击又怎么确定到底谁来触发响应呢&#xff1f;想象一下&#xff0c;在纸上画了两个大小不同的同心圆&#xff0c;然后用手指指向它里…

迁移替换AD域时,有几个关键点需要注意

在当今的数字化时代&#xff0c;企业对于身份管理和访问控制的需求日益增长。然而&#xff0c;传统的AD域控方案在面对国产化替代和业务上云的趋势时&#xff0c;逐渐显露出一些局限性。宁盾国产化身份域管作为一种迁移替换AD域控的创新解决方案&#xff0c;正逐渐崭露头角&…

通风天窗代号解析与功能介绍

通风天窗的代号通常涉及其类型、型号、尺寸及功能等多个方面。以下是对通风天窗代号的一般性释义。一、代号结构 通风天窗的代号往往遵循一定的编码规则&#xff0c;以清晰表示其特性。如在18J621-3《通风天窗》图集中&#xff0c;通风天窗的代号可能以“TCxx-xxx”的形式出现&…

云计算的成本:您需要了解的 AWS 定价信息

AWS 定价方案、免费套餐优惠以及通过预先预留容量来降低总体成本的选项。 欢迎来到雲闪世界。越来越多的企业开始转向云基础设施而非本地数据中心&#xff0c;云领域的竞争空前激烈。主要参与者甚至不惜削减成本并提供令人难以置信的折扣&#xff0c;以在云市场中占据一席之地。…

利用机器人自动回复软件,显著提升客户体验

随着科技的飞速发展及互联网普及&#xff0c;机器人自动回复软件成为了现代企业的重要工具。无论是在客户服务领域&#xff0c;还是在营销、销售等方面&#xff0c;自动回复机器人都表现出了强大的功能和显著的效果。究竟什么是机器人自动回复技术?它是如何运行的?本文将为您…

ELK学习笔记——如何给Kibana新增用户和角色

Kibana新增用户和角色 首先用超管账号登录上Kibana&#xff0c;按照下面步骤操作 1、创建角色 按图操作 2、创建用户 按图操作 3、给用户分配角色 至此&#xff0c;角色和用户绑定成功&#xff1b; 最后&#xff0c;可以退出管理员账号&#xff0c;登录这个新…

安防监控/视频汇聚EasyCVR视频监控平台级联上级,无法播放是什么原因?

EasyCVR视频监控平台&#xff0c;作为一款智能视频监控综合管理平台&#xff0c;凭借其强大的视频融合汇聚能力和灵活的视频能力&#xff0c;在各行各业的应用中发挥着越来越重要的作用。EasyCVR视频汇聚平台采用先进的图像处理技术和传输协议&#xff0c;能够确保高清、稳定的…

抖音发布Unity小游戏的errorMsg: native build failed

为了更好的性能&#xff0c;兼容更多字节平台&#xff0c;选择了Android Native IOS WebGL方案。结果Native经常报错&#xff1a;errorMsg: native build failed&#xff0c;导致IL2CCP构建失败。 最终&#xff0c;花了我两周时间&#xff01;两周啊&#xff01;还是无法解决。…

H3C SR-MPLS通过OSPF通告SID配置

首先在配置前理解几个基本概念 Prefix SID配置 统一分配和配置&#xff08;全局规划&#xff09;loopback和prefix sidPrefix SIDSRGB Base&#xff08;16000&#xff09;index Adj SID自动生成 对应SR节点间的互联链路SR节点本地标识&#xff0c;从设备本地Segment池中动态…

swagger简单使用学习

注意 一下基于spring-boot 3.0.2版本&#xff0c;该版本不支持springfox-swagger2 2.9.2会报错&#xff0c;无法访问swagger 安装 在pomx文件中添加对应的依赖 <!-- swagger --><dependency><groupId>org.springdoc</groupId><artifactId>spr…