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

UDP网络套接字编程

先来说说数据在网络上的传输过程吧,我们知道系统其实终究是根据冯诺依曼来构成的,而网络数据是怎么发的呢?

其实很简单,网络有五层。如下:

如上图,我们知道的是,每层对应的操作系统中的那些地方,有些可能说是网络有七层,其实和这个五层一样的。下面我们说说数据是怎么运输的在网络中,如下图:

如上图,其实数据在网络中是自顶向下,然后在通过以太网的网线传输到另一个主机上,在自底向上,就可以收到了,前提是在同一个局域网中,如果不在一个局域网,肯定会经过路由器的,这里就不详细说了,主要说说我们的udp协议。

我们知道了网络的五层,那么每层其实都与对应的协议等。udp协议对应在传输层(运输层)。那么我们来看看如何用udp协议实现套接字编程吧。先来看看代码:

#include <iostream>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <unordered_set>
#include <unordered_map>
using namespace std;
#define NUM 1024
int main(int argc, char *argv[])
{unordered_map<uint16_t,sockaddr_in> usdate;// 创建套接字int sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){cout << "sock enrro" << endl;exit(1);}// 绑定sockaddr_in se;memset(&se, 0, sizeof(se));se.sin_family = AF_INET;se.sin_port = htons(atoi(argv[2]));se.sin_addr.s_addr = inet_addr(argv[1]);int ret = bind(sock, (sockaddr *)&se, sizeof(se));if (ret < 0){cout << "bind enrro" << endl;exit(2);}// 服务端    1.0版本// 可以开始读取// sockaddr_in reader;// socklen_t size = sizeof(reader);// char buffer[NUM];// while (true)// {//     ssize_t r = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&reader, &size);//     buffer[r] = '\0';//     if (r > 0)//     {//         cout << buffer << endl;//     }//     else//         break;//     sendto(sock, buffer, sizeof(buffer), 0, (sockaddr *)&reader, size);//     memset(buffer, 0, sizeof(buffer));// }// close(sock);// 服务器 2.0版本 实现群聊char buffer[NUM];memset(buffer, 0, NUM);sockaddr_in reader;socklen_t size = sizeof(reader);while (true){ssize_t s = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&reader, &size);usdate.insert(make_pair(reader.sin_port, reader));cout << "插入成功" << endl;cout << ntohs(reader.sin_port) <<" "<< inet_ntoa(reader.sin_addr)<< '#' << " "<< ":" << buffer << endl;if (s > 0){for (const auto &e : usdate)sendto(sock, buffer, sizeof(buffer), 0, (sockaddr *)&(e.second), sizeof(e.second));memset(buffer, 0, NUM);}elsebreak;}close(sock);return 0;
}
#include <iostream>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
using namespace std;
#define NUM 1024
void *reads(void *args)
{// 线程分离pthread_detach(pthread_self());char buffer[NUM];// 清空buffermemset(buffer, 0, NUM);int *sc = static_cast<int *>(args);sockaddr_in reader;socklen_t len = sizeof(reader);while (true){ssize_t s = recvfrom(*sc, buffer, sizeof(buffer) - 1, 0, (sockaddr *)&reader, &len);if (s > 0){cout << buffer << endl;memset(buffer, 0, NUM);}elsebreak;}return nullptr;
}
int main(int argc, char *argv[])
{int sock = socket(AF_INET, SOCK_DGRAM, 0);if (sock < 0){cout << "sock enrro" << endl;exit(1);}char buffer[NUM];memset(buffer, 0, NUM);pthread_t tid;pthread_create(&tid, nullptr, reads, &sock);sockaddr_in clinet;memset(&clinet, 0, sizeof(clinet));clinet.sin_family = AF_INET;clinet.sin_addr.s_addr = inet_addr(argv[1]);clinet.sin_port = htons(atoi(argv[2]));while (true){cout << "你要输入" << endl;cin >> buffer;ssize_t s = sendto(sock, buffer, sizeof(buffer), 0, (sockaddr *)&(clinet), sizeof(clinet));if (s > 0)memset(buffer, 0, NUM);elsebreak;}close(sock);return 0;
}

这是我的服务端和客户端的代码,分了单人聊天和多人聊天。下面就讲解一下吧。

什么是端口号:主机中能表示一个唯一的进程的编号

什么是ip地址:其实ip地址是网络层对应的主机地址。

什么是mac地址:这个网卡的地址,一般出厂的时候就会确定,且不能修改

什么是套接字:IP+端口号

我们首先可以根据套接字找到网络中唯一的一个主机上进程,此处不考虑ip地址重复问题。假设ip地址不重复。所以我们要进行udp套接字编程,首先要创建套接字。也就是我上图代码中的socket这个函数,然后绑定地址和端口,这个就可以用我们main函数中的参数了。创建完套接字和绑定完成以后,我们就可以通信了,我们用的这些函数其实就是系统调用,是udp的一些函数暴露给用户层的系统调用。

大概知道了怎么用udp编程,那么此时有些伙伴可能有些疑问了。我们在系统层面上pid也可以表示进程的唯一性,为啥不用PID表示端口号呢?其实也很简单,原因就是网络层是这么表示的,就好比你的名字一样,在外面大家都叫你名字,回到家家里面的人都叫你小名,一样的道理。

然后就是有些人可能没有理解数据是怎么从下往上,从上往下的。其实很好理解,因我们在写代码的时候,我们是属于用户层的。而我们传输层的系统调用接口,那么说明他这个数据肯定是要进内核的,而我们的另一个主机接收到信息后,我们用的打印函数,又是用户层的,所以就类似于一个轮回。所以这样就可以很好的理解了。

然后就是一些编码的注意事项了,在客户端我用了多线程来实现了读数据和写数据的解耦,这个其实在单人聊天中没什么影响,再多人聊天中就不可以了。假设单人聊天就要先发在读。因为再多人聊天中,我们预期是一个人发,多个人收,如果还是用这个代码的话,那么 如果开启服务端的时候,多个人你同时建立连接,那么此时如果有其中一个人发了信息,并且假设其他人都没有发信息,那么此时就会导致其他人卡在写的界面,因为他们没有写,所以没办法读信息。所以此时我们这里必须要实现成多线程,一个写,一个读,读写解耦。两个互不影响。建议使用线程,不用进程,且不说多进程可不可以实现这个功能,就算是实现了,那么此时它的消耗是很大的。(多进程也可以实现这个功能),如果用多进程,那么此时我们要考虑的是,如何回收这个子进程,肯定不可以阻塞等待,如果用waitpid且不是阻塞等待的话,那么此时我们要写成循环,要不断去检测子进程是否完成任务。或是可以在子进程中在frok,让孙子进程执行任务,子进程退出,此时就会形成孤儿进程,会被1号进程领养,所以不用担心资源泄露,但是这样很明显很麻烦,还不如用线程,且消耗还比进程小。

以上就是这篇文章的内容,希望大家支持,如果对你有用,希望支持一下!!!!

相关文章:

UDP网络套接字编程

先来说说数据在网络上的传输过程吧&#xff0c;我们知道系统其实终究是根据冯诺依曼来构成的&#xff0c;而网络数据是怎么发的呢&#xff1f; 其实很简单&#xff0c;网络有五层。如下&#xff1a; 如上图&#xff0c;我们知道的是&#xff0c;每层对应的操作系统中的那些地方…...

【苏州元德维康生物医药-注册】

...

从零带你底层实现unordered_map (1)

&#x1f4af; 博客内容&#xff1a;从零带你实现unordered_map &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准C后端工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家…...

第六届浙江省大学生网络与信息安全竞赛 2023年 初赛/决赛 WEB方向 Writeup

-------------------【初赛】------------------- easy php 简单反序列化 __debuginfo()魔术方法打印所需调试信息&#xff0c;反序列化时候执行&#xff01; 链子如下&#xff1a; BBB::__debuginfo()->CCC::__toString()->AAA::__call()EXP&#xff1a; <?php…...

设计模式篇---装饰模式

文章目录 概念结构实例总结 概念 装饰模式&#xff1a;动态的给一个对象增加一些额外的职责。就扩展功能而言&#xff0c;装饰模式提供了 一种比使用子类更加灵活的替代方案。 装饰模式是一种对象结构型模式&#xff0c;它以对客户透明的方式动态地给一个对象附加上更多的责任…...

JAXB:根据Java文件生成XML schema文件

说明 JAXB有个schemagen脚本&#xff0c;可以根据Java文件生成XML schema。这个工具在JAXB独立发布包中有&#xff0c;可以从官网下载JAXB的独立发布包&#xff1a; https://eclipse-ee4j.github.io/jaxb-ri/ 示例 使用schemagen -d <path> <java files>格式 …...

opencv(5): 滤波器

滤波的作用&#xff1a;一幅图像通过滤波器得到另一幅图像&#xff1b;其中滤波器又称为卷积核&#xff0c;滤波的过程称为卷积。 锐化&#xff1a;边缘变清晰 低通滤波&#xff08;Low-pass Filtering&#xff09;&#xff1a; 目标&#xff1a;去除图像中的高频成分&#…...

《微信小程序开发从入门到实战》学习二十二

3.3 开发创建投票页面 3.3.10 使用switch开关组件 用switch开关组件增加一个设置是否匿名投票的功能。 switch常用属性如下&#xff1a; checked 开还是关&#xff0c;默认false关 disabled 是否禁用&#xff0c;默认false不禁用&#xff0…...

LLM模型-讯飞星火与百度文心api调用

spark-wenxin 1-讯飞星火1_1-SparkApi.py1_2- Chat_spark.py1_3-调用api 2-百度文心2_1.code 3-两者之间比较与openai 1-讯飞星火 进入讯飞官网进行创建应用&#xff0c;获取相关密钥APPID&#xff0c;APISecret&#xff0c;APIKey&#xff0c;选择最新版本 首次调用讯飞官方a…...

AIGC ChatGPT 4 将数据接口文件使用Python进行入库Mysql

数据分析,数据处理的过程,往往将采集到的数据,或者从生产库过来的接口文件,我们都需要进行入库操作。 如下图数据: 将这样的数据接口文件,进行入库,插入到Mysql数据库中。 用Python代码来完成。 ChatGPT4来完成代码输入。 ChatGPT4完整内容如下: 这个任务可以使用`…...

Loguru:一个超酷的Python库

在项目中&#xff0c;了解代码运行情况至关重要&#xff0c;特别是遇到Bug需要排除问题的时候&#xff0c;而这正是日志记录发挥作用的地方。对于Python开发者来说&#xff0c;Loguru是一个简单但功能强大的日志记录库&#xff0c;它使得跟踪代码的行为变得轻松而高效。 什么是…...

cloud的概念

"Cloud"&#xff08;云&#xff09;通常指的是云计算&#xff08;cloud computing&#xff09;领域。云计算是一种通过网络&#xff08;通常是互联网&#xff09;提供计算资源和服务的模型。这些计算资源包括计算能力、存储空间、数据库、网络、分析能力等。云计算模…...

物联网赋能:WIFI HaLow在无线连接中的优势

在探讨无线网络连接时&#xff0c;我们不难发现&#xff0c;WIFI已经成为我们日常生活中不可或缺的一部分&#xff0c;承载了半数以上的互联网流量&#xff0c;并在家庭、学校、娱乐场所等各种场合广泛应用。然而&#xff0c;尽管WIFI4、WIFI5和WIFI6等协议无处不在&#xff0c…...

淘宝商品详情数据接口(Taobao.item_get)

淘宝商品详情接口是一种程序化的接口&#xff0c;允许开发者根据商品ID或商品链接&#xff0c;获取淘宝平台上的商品详细信息。通过这个接口&#xff0c;开发者可以方便地获取商品的标题、价格、销量、描述等数据&#xff0c;进而提供给用户进行展示和购买。 使用淘宝商品详情…...

视频剪辑方法:一键批量调整色调的高效技巧

在视频剪辑的过程中&#xff0c;色调调整是一项非常重要的工作。它能够改变影片的氛围、情感和视觉效果&#xff0c;更好地沉浸在影片的情境中。然而&#xff0c;对于许多视频剪辑师来说&#xff0c;批量调整色调是一项非常繁琐的任务&#xff0c;需要耗费大量的时间和精力。色…...

NAS层协议栈学习笔记

NAS(Non-Access Stratum)是无线网络中非接入层及包括移动性管理(MM)和会话管理(SM)协议 &#xff0c;在5G(NR)系统中连接管理(Connection Management)用于建立和释放UE与AMF之间的控制面(CP)信令连接。 5G中移动性管理是通过NAS信令在UE与核心网之间进行交互的&#xff0c;连接…...

前端食堂技术周刊第 105 期:TS 5.3 RC、Vite 5.0、W3C 新任 CEO、有害的 Pinia 模式、2024 更快的 Web

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;金桂普洱 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来看下…...

jenkins 使用原生 git clone 命令,指定ssh密钥文件

使用环境变量 GIT_SSH_COMMAND 从Git版本2.3.0可以使用环境变量GIT_SSH_COMMAND&#xff0c;如下所示&#xff1a; GIT_SSH_COMMAND"ssh -i ~/.ssh/id_rsa_example" git clone example请注意&#xff0c;-i有时可以被您的配置文件覆盖&#xff0c;在这种情况下&…...

cobol数据类型

数据类型 数据部&#xff08;data division&#xff09;是用来描述程序中使用的变量的。 data name 数据名称 数据名称必须在数据部中定义&#xff0c;才能在过程部中使用。必须有一个用户自定义的名称&#xff0c;不能使用关键字&#xff0c;为存储实际数据的存储单元提供引…...

Java Web——JS中的BOM

1. Web API概述 Web API 是指浏览器提供的一套接口&#xff0c;这些接口允许开发人员使用 JavaScript&#xff08;JS&#xff09;来操作浏览器功能和页面元素。通过 Web API&#xff0c;开发人员可以与浏览器进行交互&#xff0c;以实现更复杂的功能和效果。 1.1. 初识Web AP…...

机器学习Day5-模型诊断

实现机器学习算法的技巧。当我们训练模型或使用模型时&#xff0c;发现预测误差很 大&#xff0c;可以考虑进行以下优化&#xff1a; &#xff08;1&#xff09;获取更多的训练样本 &#xff08;2&#xff09;使用更少的特征 &#xff08;3&#xff09;获取其他特征 &#xff…...

macOS 安装 Grafana + Prometheus + Node Exporter

macOS 安装指南&#xff1a;Grafana Prometheus Node Exporter 目录简介&#x1f680; 快速开始 安装 Homebrew1. 安装 Homebrew2. 更新 Homebrew 安装 Node Exporter使用 Homebrew 安装验证 Node Exporter 安装 Prometheus使用 Homebrew 安装验证安装 安装 Grafana使用 Home…...

02业务流程的定义

1.要想用好业务流程&#xff0c;首先必须得了解流程与认识流程&#xff0c;什么是业务流程。在认识流程之前&#xff0c;首先要理清两个基本概念&#xff0c;业务和流程。 业务指的是&#xff1a;个人的或者摸个机构的专业工作。流程&#xff0c;原本指的是水的路程&#xff0…...

React 编译器

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…...

DALI DT6与DALI DT8介绍

“DT”全称Device Type&#xff0c;是DALI-2 标准协议中的IEC 62386-102(即为Part 102)部分对不同类型的控制设备进行一个区分。不同的Device Type代表不同特性的控制设备&#xff0c;也代表了这种控制设备拥有的扩展的特性。 在DALI&#xff08;数字可寻址照明接口&#xff09…...

shell中与>和<相关的数据流重定向操作符整理

shell中与>和<相关的数据流重定向操作符整理 输出重定向操作符>>>2>2>>&> 或 >&&>> 输入重定向操作符<<<<<< 组合重定向2>&1 文件描述符相关重定向[n]< file 和 [n]> file>&- 和 <&…...

黑马点评项目01——短信登录以及登录校验的细节

1.短信登录 1.1 Session方式实现 前端点击发送验证码&#xff0c;后端生成验证码后&#xff0c;向session中存放键值对&#xff0c;键是"code"&#xff0c;值是验证码&#xff1b;然后&#xff0c;后端生成sessionID以Cookie的方式发给前端&#xff0c;前端拿到后&a…...

VR 技术在农业领域或许是一抹新曙光​

在科技日新月异的今天&#xff0c;VR(虚拟现实)技术已不再局限于游戏、影视等娱乐范畴&#xff0c;正逐步渗透到各个传统行业&#xff0c;为其带来全新的发展契机&#xff0c;农业领域便是其中之一。VR 技术利用计算机生成三维虚拟世界&#xff0c;给予用户视觉、听觉、触觉等多…...

理解 Vue 2 的响应式原理:数据劫持与依赖收集的背后

在Vue2中,响应式系统是一切魔法的源头,无论是模板中的数据绑定,还是computed,watch的精准监听,都离不开Vue背后的响应式机制,本文将从源码角度出发,结合实例,深入剖析vue2是如何通过数据劫持(Object.defineProperty)和依赖收集实现响应式的 一.Vue2响应式系统基本原理 vue2中…...

小程序 - 视图与逻辑

个人简介 👨‍💻‍个人主页: 魔术师 📖学习方向: 主攻前端方向,正逐渐往全栈发展 🚴个人状态: 研发工程师,现效力于政务服务网事业 🇨🇳人生格言: “心有多大,舞台就有多大。” 📚推荐学习: 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒T…...