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号进程领养,所以不用担心资源泄露,但是这样很明显很麻烦,还不如用线程,且消耗还比进程小。

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

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

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

相关文章

系列一、堆里面的分区:Eden、From、To、老年代各自的特点

一、堆里面的分区&#xff1a;Eden、From、To、老年代各自的特点 堆是对象共享的区域&#xff0c;也是垃圾回收器主要工作的地方。主要分为新生区、养老区和元空间&#xff0c;而这三块地方中GC主要工作在新生区和养老区&#xff0c;其中新生区占1/3、养老区占2/3&#xff0c;新…

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

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

openssl1.0.2版本Windows安装问题

之前安装过1.1版本&#xff0c;Windows环境下C 安装OpenSSL库 源码编译及使用&#xff08;VS2019&#xff09;_vs2019安装openssl_肥宝Fable的博客-CSDN博客 后来发现linux编译不过&#xff0c;以为是版本问题&#xff0c;相差太大&#xff0c;所以降一下版本&#xff0c;以免…

NAS层协议栈学习笔记

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

设计模式常见面试题

简单梳理下二十三种设计模式&#xff0c;在使用设计模式的时候&#xff0c;不仅要对其分类了然于胸&#xff0c;还要了解每个设计模式的应用场景、设计与实现&#xff0c;以及其优缺点。同时&#xff0c;还要能区分功能相近的设计模式&#xff0c;避免出现误用的情况。 什么是…

第十一周任务总结

本周任务总结 本周物联网方面主要继续进行网关的二次开发与规则引擎实现设备联动的实现 非物联网方面主要复习了docker的使用与算法的学习 1.网关的二次开发&#xff0c;本周将实现debug调试输出的文件下载到了网关&#xff0c;但网关出了问题无法连接&#xff0c;最终跟客服…

Web之CSS笔记

Web之HTML、CSS、JS 二、CSS&#xff08;Cascading Style Sheets层叠样式表&#xff09;CSS与HTML的结合方式CSS选择器CSS基本属性CSS伪类DIVCSS轮廓CSS边框盒子模型CSS定位 Web之HTML笔记 Web之JavaScript(jQuery)笔记 二、CSS&#xff08;Cascading Style Sheets层叠样式表&…

Selenium安装WebDriver最新Chrome驱动(含116/117/118/119)

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

Halcon Solution Guide I basics(2): Image Acquisition(图像加载)

文章目录 文章专栏前言文章解读文章开头流程图算子介绍案例自主练习读取一张图片读取多张图片 文章专栏 Halcon开发 Halcon学习 练习项目gitee仓库 前言 今天来看Halcon的第二章&#xff0c;图像获取。在第二章之后&#xff0c;后面文章就会提供案例了。到时候我会尽量完成每一…

Kotlin 知识体系

Kotlin 知识体系 1、Kotlin 文档2、Kotlin 基础3、桌面应用程序4、Android 与 iOS 应用程序 1、Kotlin 文档 Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复…

【数据结构初阶】单链表SLlist

描述 不同于顺序表&#xff0c;顺序表的数据是存储在一个连续的空间里的 而链表它是链接起来的结构体地址。 所以我们不用像顺序表一样先创建一块空间出来&#xff0c;而是创建一个能存数据节点和节点与下一个节点之间的连接&#xff1b; 所以&#xff1a;“一个能存数据节点…

鸿蒙:从0到“Hello Harmony”

效果展示 一.概述 明年华为鸿蒙就不再兼容Android生态了&#xff0c;作为拥有7亿终端用户的华为&#xff0c;建立自己的生态也是理所当然。 所以对HarmonyOS的研究也是众多开发者绕不开的坎了。 今天这篇博文主要实现一个“Hello Harmony&#xff01;”的Demo。 二.官方链接…

场景交互与场景漫游-osgGA库(5)

osgGA库 osgGA库是OSG的一个附加的工具库&#xff0c;它为用户提供各种事件处理及操作处理。通过osgGA库读者可以像控制Windows窗口一样来处理各种事件 osgGA的事件处理器主要由两大部分组成&#xff0c;即事件适配器和动作适配器。osgGA:GUIEventHandler类主要提供了窗口系统的…

基于单片机体温脉搏检测控制系统及源程序

一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20传感器检测体温。 3、红外对接管采集心率值送到液晶1602显示。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 /lcd1602初始化设置*/ void init_1602() { write_com(0x38); //显示…

二元分类模型评估方法

文章目录 前言一、混淆矩阵二、准确率三、精确率&召回率四、F1分数五、ROC 曲线六、AUC&#xff08;曲线下面积&#xff09;七、P-R曲线类别不平衡问题中如何选择PR与ROC 八、 Python 实现代码混淆矩阵、命中率、覆盖率、F1值ROC曲线、AUC面积 指标 公式 意义 真正例 (TP)被…

【项目设计】网络版五子棋游戏

文章目录 一、项目介绍1. 项目简介2. 开发环境3. 核心技术4. 开发阶段 二、环境搭建1. 安装 wget 工具2. 更换 yum 源3. 安装 lrzsz 传输工具4. 安装⾼版本 gcc/g 编译器5. 安装 gdb 调试器6. 安装分布式版本控制工具 git7. 安装 cmake8. 安装 boost 库9. 安装 Jsoncpp 库10. 安…

四旋翼无人机的飞行原理--【其利天下分享】

近年来&#xff0c;无人机在多领域的便捷应用促使其迅猛的发展&#xff0c;如近年来的多场战争&#xff0c;无人机的战场运用发挥得淋漓尽致。 下面我们针对生活中常见的四旋翼无人机的飞行原理做个基础的介绍&#xff0c;以飨各位对无人机有兴趣的朋友。 一&#xff1a;四旋翼…

春秋云境靶场CVE-2022-28512漏洞复现(sql手工注入)

文章目录 前言一、CVE-2022-28512靶场简述二、找注入点三、CVE-2022-28512漏洞复现1、判断注入点2、爆显位个数3、爆显位位置4 、爆数据库名5、爆数据库表名6、爆数据库列名7、爆数据库数据 总结 前言 此文章只用于学习和反思巩固sql注入知识&#xff0c;禁止用于做非法攻击。…

腐蚀监测常用技术及作用

上次我们介绍了设备状态监测中的红外热像技术>>热成像仪的工作原理及在工业设备状态监测中的应用&#xff0c;这次我们一起来探讨腐蚀监测技术方面的内容。 在工业领域中&#xff0c;腐蚀监测技术是腐蚀控制的重要部分和可靠而有效的手段。通过对设备的腐蚀情况进行监测和…