TCP和UDP可以使用同一个端口号吗?

TCP和UDP可以使用同一个端口号吗?

首先说答案:可以。怎么理解呢?

我想这个问题要从计算机网络通信谈起,学过计算机网络的同学,可能都还记得7层或者4层网络模型,TCP/UDP属于其中的传输层协议,在传输层之下是网络层,网络层主要通过IP协议来进行通信,这也是我们日常程序开发中能够接触到的最底层了,再往下的数据链路层和物理层就不是我们这些普通程序员需要关心的了。

IP

我们先具体看下网络层。在IP网路层,发送者向接收者传输数据的时候,首先需要知道接收者的IP地址,IP地址可以在网络中唯一标识一台计算机,然后数据就可以根据IP协议抵达接收者所在的计算机,但是接收者所在的计算机上运行了几十个程序,计算机应该把这个数据交给哪个程序呢?

端口号

这就像快递员到达了一栋大楼,下一步它怎么把快递送到对应的用户手中呢?聪明的你一定想到了,那就是门牌号。

在计算机中,端口号就是门牌号。计算机的操作系统可以为不同的程序绑定不同的端口号,这样发送者发送数据时不仅要设置接收者的IP,还要加上接收者的端口号,如此接收者所在的计算机就能把数据转发给正确的程序了。

TCP/UDP

那么TCP和UDP能不能使用同一个端口号呢?其实在查找端口号之前还有一个传输层协议的处理过程,操作系统收到数据后,会先查看数据包使用的是TCP协议还是UDP协议,然后再根据协议进行不同的解析处理,提取到数据后,再转发到拥有对应端口的程序。

所以TCP和UDP是可以使用相同的端口号的,这在现实中也是常见的。比如 DNS(域名系统)可能需要同时支持 TCP 和 UDP 查询,这两种查询就都可以通过53这个标准端口来进行接收和响应。

但是在同一个传输协议下,端口号就不能相同了。如果相同,操作系统的协议栈就不知道该把这个数据包转给哪个程序了,这种设计会增加很多麻烦。

有的同学可能会观察到一个现象,那就是同一个计算机上的多个网站可以共享80或者443端口,这其实是应用层的能力,这些网站都寄宿在同一个Web服务器程序上,这个Web服务器程序绑定了80端口,Web服务器收到数据后再根据HTTP协议中的主机头(可以理解成域名)转发给不同的网站程序。

还有,如果你的电脑上有多个IP,那就更没有问题了。不同的IP代表不同的网络接口,即使都使用TCP协议,只要IP不同,端口号一样也完全不会冲突。

“IP+传输层协议+端口号”就是我们常说的套接字,它能确保数据从一个网络程序传递到另一个网络程序。大家如果直接使用TCP和UDP编程,就需要手动为套接字设置这几个参数。

示例

口说无凭,再给大家写个demo,使用go语言,简单易懂:

下边的程序会启动一个TCP服务器和一个UDP服务器,它们绑定相同的IP和端口号。这里为了方便测试,使用了127.0.0.1这个本机IP,你也可以换成局域网或者公网IP。

package mainimport ("fmt""net""os"
)func main() {// 定义监听的端口port := "127.0.0.1:12345"// 启动TCP服务器go startTCPServer(port)// 启动UDP服务器startUDPServer(port)
}func startTCPServer(port string) {// 通过TCP协议监听端口l, err := net.Listen("tcp", port)if err != nil {fmt.Println("Error listening:", err.Error())os.Exit(1)}defer l.Close()fmt.Println("TCP Server Listening on " + port)// 持续接收TCP数据for {conn, err := l.Accept()if err != nil {fmt.Println("Error accepting: ", err.Error())os.Exit(1)}fmt.Println("Received TCP connection")conn.Close()}
}func startUDPServer(port string) {// 通过UDP协议监听端口addr, err := net.ResolveUDPAddr("udp", port)if err != nil {fmt.Println("Error resolving: ", err.Error())os.Exit(1)}conn, err := net.ListenUDP("udp", addr)if err != nil {fmt.Println("Error listening: ", err.Error())os.Exit(1)}defer conn.Close()fmt.Println("UDP Server Listening on " + port)buffer := make([]byte, 1024)// 持续接收UDP数据for {n, _, err := conn.ReadFromUDP(buffer)if err != nil {fmt.Println("Error reading: ", err.Error())continue}fmt.Printf("Received UDP packet: %s\n", string(buffer[:n]))}
}

然后再创建两个客户端,一个是TCP客户端:

package mainimport ("fmt""net""os"
)func main() {// 连接到服务器conn, err := net.Dial("tcp", "localhost:12345")if err != nil {fmt.Println("Error connecting:", err.Error())os.Exit(1)}defer conn.Close()// 发送数据_, err = conn.Write([]byte("Hello TCP Server!"))if err != nil {fmt.Println("Error sending data:", err.Error())return}fmt.Println("Message sent to TCP server")
}

另一个是UDP客户端:

package mainimport ("fmt""net""os"
)func main() {ServerAddr, err := net.ResolveUDPAddr("udp", "localhost:12345")if err != nil {fmt.Println("Error resolving: ", err.Error())os.Exit(1)}conn, err := net.DialUDP("udp", nil, ServerAddr)if err != nil {fmt.Println("Error dialing: ", err.Error())os.Exit(1)}defer conn.Close()// 发送数据_, err = conn.Write([]byte("Hello UDP Server!"))if err != nil {fmt.Println("Error sending data:", err.Error())return}fmt.Println("Message sent to UDP server")
}

我们可以看到,客户端发起请求的时候都使用了 localhost:12345 这个目标地址,其中的localhost 实际上是个域名,它会被本地计算机解析为 127.0.0.1。这块不清楚的可以看我之前写的这篇:

实际运行效果如下:


最后总结下:在网络通信中,同一台计算机中,TCP和UDP协议可以使用相同的端口号。每个网络进程中的套接字地址都是唯一的,由三元组(IP地址,传输层协议,端口号)标识。操作系统会根据数据包中的传输层协议(TCP或UDP)以及端口号,将接收到的数据正确地交付给相应的应用程序。

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

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

相关文章

浅析扩散模型与图像生成【应用篇】(七)——Prompt-to-Prpmpt

7. Prompt-to-Prompt Image Editing with Cross Attention Control 本文提出一种利用交叉注意力机制实现文本驱动的图像编辑方法,可以对生成图像中的对象进行替换,整体改变图像的风格,或改变某个词对生成图像的影响程度,如下图所示…

《程序员的职业迷宫:选择你的职业赛道》

程序员如何选择职业赛道? 大家好,我是小明,一名在编程迷宫中探索的程序员。作为这个庞大迷宫的探险者,我深知选择适合自己的职业赛道有多么重要。今天,我将分享一些关于如何选择职业赛道的心得,希望能够帮…

网络编程作业day6

数据库操作的增、删、改完成 #include <myhead.h>//查询的回调函数 int callback(void* data,int count,char** argv, char** columnName) {//count是字段数//argv是字段内容//columnName是字段名称for(int i0;i<count;i) {printf("%s%s\n", columnName[…

2024全国水科技大会暨新能源及电子行业废水论坛(十一)

一、会议背景 为深入学习贯彻《中共中央、国务院关于全面推进美丽中国建设的意见》&#xff0c;全面贯彻实施《固体废物污染环境防治法》、《“十四五”全国城市基础设施建设规划》&#xff0c;推进我国污泥处理工程建设&#xff0c;提高处理产物资源化利用水平&#xff0c;促进…

Python内置模块

目录 什么是模块 模块分类 通过模块创建者分类 系统内置模块 第三方模块 在线安装 离线安装 模块导入 math和random模块介绍 math模块 random模块 什么是模块 在我们编写程序时&#xff0c;需要导入包。例如随机数的产生&#xff0c;需要import random。import XXX&…

XGboost的整理

XGboost&#xff08;extreme gradient boosting&#xff09;:高效实现了GBDT算法并进行了算法和工程上的许多改进。 XGboost的思路&#xff1a; 目标&#xff1a;建立k个回归树&#xff0c;使得树群的预测尽量接近真实值&#xff08;准确率&#xff09;而且有尽量大的泛化能力…

Java项目:39 springboot008房屋租赁系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 房屋租赁系统的设计基于现有的网络平台&#xff0c;主要有管理员、房东、用户三个角色 管理员可以在线查看系统已有的人中心、房屋类型管理、房屋信息…

创建java项目

文章目录 一、安装idea二、创建一个java项目1.设置名称 项目路径 安装JDK&#xff08;自己选择一个位置存放JDK&#xff09;2.创建完成之后 在src文件夹下创package包 再在包下创建Class类3. hellojava类创建完成设置打印语句 输出HelloJava 一、安装idea 官网地址 二、创建一…

不买后悔的阿里云服务器租用价格表_优惠活动整理_2024新版

2024阿里云服务器优惠活动政策整理&#xff0c;阿里云99计划ECS云服务器2核2G3M带宽99元一年、2核4G5M优惠价格199元一年&#xff0c;轻量应用服务器2核2G3M服务器61元一年、2核4G4M带宽165元1年&#xff0c;云服务器4核16G10M带宽26元1个月、149元半年&#xff0c;云服务器8核…

使用Http请求下载文件带来的问题

java.io.IOException: Broken pipe 当使用http请求的方式将文件作为响应内容给浏览器&#xff0c;这个时候如果浏览器未开启自动下载(浏览器可能会终止这个tcp连接)&#xff0c;文件不会下载成功&#xff0c;但是这个时候请求已经到达服务器&#xff0c;如果这个时候&#xff0…

Dynamo初学常识梳理(四)——Revit图元

希望想学 Dynamo 的小伙伴坚持住&#xff0c;每天积累一点点知识&#xff0c;Dynamo 你很快就能上手的&#xff01;Dynamo 并不是你想的那样难学哦&#xff01; 今天要讲的是如何从 Dynamo 中获取 Revit 的图元&#xff0c;这些节点很常用&#xff0c;不需要全背下来&#xff0…

指针运算笔试题解析

题目1&#xff1a; int main() { int a[5] { 1, 2, 3, 4, 5 }; int* ptr (int*)(&a 1); printf("%d %d", *(a 1), *(ptr - 1)); return 0; } ptr中存放了整个数组的地址&#xff0c;ptr是int*类型&#xff0c;&a1跳到5的地址后又被强制类…

算法DFS 复习

思路&#xff1a;for 代表的是每一位的纵向&#xff0c;数字变化&#xff0c;dfs 代表的是横向的&#xff0c;位置变化。vis 来做到每个枚举的数不重复&#xff0c;并且要在搜索前记录&#xff0c;搜索后还原。模拟该样例 dfs3 的时候是输出&#xff0c;dfs0&#xff0c;1&…

【DAY05 软考中级备考笔记】线性表,栈和队列,串数组矩阵和广义表

线性表&#xff0c;栈和队列&#xff0c;串数组矩阵和广义表 2月28日 – 天气&#xff1a;阴转晴 时隔好几天没有学习了&#xff0c;今天补上。明天发工资&#xff0c;开心&#x1f604; 1. 线性表 1.1 线性表的结构 首先线性表的结构分为物理结构和逻辑结构 物理结构按照实…

【LabVIEW FPGA】CIC滤波器

一、CIC滤波器应用概述 在通信数字信号上下变频时&#xff0c;经常会用到对数字信号的升采样和降采样&#xff0c;即通过CIC数字速率器实现变采样率。 二、滤波器IP 首先设置滤波器基本参数&#xff08;filter specification&#xff09; 滤波器类型&#xff08;Filter Type…

uipath调用js代码

1&#xff0c;调用js代码&#xff0c;不带参数&#xff0c;没有返回值 为了去掉按钮的disabled属性 function(){ document.getElementsByClassName(submitBtn)[0].removeAttribute(disabled); } 2&#xff0c;调用js代码&#xff0c;带参数&#xff0c;没有返回值 输入参数&a…

【conda】实现conda环境迁移的4种方式

文章目录 方案1: 使用conda pack制作压缩包并在目标环境解压使用方案2: 使用package列表文件重新创建conda环境方案3: scp将环境文件夹拷贝到目标主机上方案4: 通过--clone先克隆一个环境再conda pack打包迁移 方案1: 使用conda pack制作压缩包并在目标环境解压使用 适合离线环…

基于51单片机的四位并行数据主从机传输设计

基于51单片机的四位并行数据主从机传输设计[proteus仿真] 主从机通信系统这个题目算是课程设计和毕业设计中常见的题目了&#xff0c;本期是一个基于51单片机的四位并行数据主从机传输设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】&#xff0c;赞赏任意文…

WPF调用webapi并展示数据(一):WPF页面的构建

有错误欢迎大家给我指正 本项目为WPFPrismnet6.0 RestSharp调用API UI为MaterialDesignThemes EF Core自动生成数据库 效果展示&#xff1a; 项目启动后点击待办事项进入数据展示页 源码地址&#xff1a;绎Ronion/WPF.ToDo (gitee.com) 1.准备 1.1创建WPF项目 1.2 创建…

Axure 入门文档 文件格式 全局样式 元件居中

文件格式 .rp 原型文件.rplib:元件库文件.rpteam 团队项目文件.html 项目网页文件 批量设置居中 选中多个&#xff0c;然后上方任务栏即可设置 设置自定义页面视图尺寸 项目-自适应视图设置 点击页面空白处就可以使用 添加元件说明 当一个元件创建好&#xff0c;可以设…