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

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

我想这个问题要从计算机网络通信谈起,学过计算机网络的同学,可能都还记得7层或者4层网络模型,TCP/UDP属于其中的传输层协议,在传输层之下是网络层,网络层主要通过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 main

import (
"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 main

import (
"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 main

import (
"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)以及端口号,将接收到的数据正确地交付给相应的应用程序。

TCP和UDP可以使用同一个端口号吗?的更多相关文章

  1. python网络编程,通过服务名称和会话类型(tcp,udp)获取端口号,简单的异常处理

    作为一个php程序员,同时有对网络方面感兴趣,php就比较蛋疼了,所以就抽了些时间看python 之前学python基础因为工作原因,断断续续的看了个基础,差不多是可以写代码了 最近在看<pyt ...

  2. 图解 TCP/IP 第六章 TCP与UDP 笔记6.1 传输层的作用

     图解 TCP/IP  第六章 TCP与UDP   笔记6.1 传输层的作用   传输层必须指出这个具体的程序,为了实现这一功能,使用端口号这样一种识别码.根据端口号,就可以识别在传输层上一层的应用程 ...

  3. TCP与UDP 笔记

    本文整理自:<图解TCP/IP 第5版>作者:[日] 竹下隆史,[日] 村山公保,[日] 荒井透,[日] 苅田幸雄 著译者:乌尼日其其格出版时间:2013-07 TCP提供可靠的通信传输, ...

  4. mac地址、IP地址和端口号

    看了很多遍,才整理出来我对整个通信过程的理解,大致如下,后期会不断学习补充更正: 在利用TCP/IP协议族进行通信的时候,有三个比较关键的确认身份的信息:mac地址.IP地址和端口号. mac地址是在 ...

  5. Service Name Port Number Transport Protocol tcp udp 端口号16bit

    https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol The DHCP employs a connectionless  ...

  6. TCP、UDP、IP 协议分析

    http://rabbit.xttc.edu.cn/rabbit/htm/artical/201091145609.shtml  http://bhsc881114.github.io/2015/06 ...

  7. TCP、UDP、IP协议分析

    此篇文章的原创作者是:草根老师博客(程姚根) chengyaogen.blog.chinaunix.net 感谢原作者! 互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如: ...

  8. (转)TCP、UDP、IP协议

    原文地址:http://blog.chinaunix.net/uid-26833883-id-3627644.html   互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如 ...

  9. TCP/IP协议栈与数据包封装+TCP与UDP区别

    ISO制定的OSI参考模型的过于庞大.复杂招致了许多批评.与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用.如图2-1所示,是TCP/IP参考模型和OSI参考模型的对比示意图. T ...

  10. CentOS7查看开放端口命令及开放端口号

    CentOS 7查看以开放端口命令:firewall-cmd —list-ports 查看端口是否开放命令:第一个方法就是使用lsof -i:端口号命令行,例如lsof -i:80.如果没有任何信息输 ...

随机推荐

  1. TS声明promise返回来的数据类型

    promise返回来的数据类型 interface backResult{ code: number, data: { name:string,age:number}[], //数组里面的对象类型,这 ...

  2. 【小测试】玩一玩 VictoriaMetrics 的 force merge

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 我是期望通过备份来建立 VictoriaMetrics 的 ...

  3. 【K哥爬虫普法】孤注一掷的爬虫er,究竟还要误入歧途多远?

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  4. apb vnext DynamicCient

    1.在需要的服务客户端(xx.HttpApi.Client)Nuget 引用和模块依赖 引用:VOLO.APB.HTTP.CLENT [dependsOn(typeof(AbpHttpClientMo ...

  5. 在mac中双击执行python

    执行python脚本 mac有内置的python,但还是建议你自己安装一个python,如果没有卸载mac自带的python2.7,当你需要使用python3执行脚本时,python命令需要改为pyt ...

  6. 强化学习技巧五:numba提速python程序

    numba是一款可以将python函数编译为机器代码的JIT编译器,经过numba编译的python代码(仅限数组运算),其运行速度可以接近C或FORTRAN语言. numba使用情况 使用numpy ...

  7. C/C++ 实现FTP文件上传下载

    FTP(文件传输协议)是一种用于在网络上传输文件的标准协议.它属于因特网标准化的协议族之一,为文件的上传.下载和文件管理提供了一种标准化的方法,在Windows系统中操作FTP上传下载可以使用WinI ...

  8. 4.2 Windows驱动开发:内核中进程线程与模块

    内核进程线程和模块是操作系统内核中非常重要的概念.它们是操作系统的核心部分,用于管理系统资源和处理系统请求.在驱动安全开发中,理解内核进程线程和模块的概念对于编写安全的内核驱动程序至关重要. 内核进程 ...

  9. 4.5 C++ Boost 文件目录操作库

    Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量.可移植.高效的C应用程序.Boost库可以作为标准C库的后备,通常被称为准标准 ...

  10. sed文本处理工具常见用法

    sed的全称是stream editor, 表示它是一个流编译器.可以处理文本内容和终端命令的流标准输出,对文本做查找,替换,插入,删除操作. 它是把文件中的内容逐行copy到缓冲区,然后在缓冲区中进 ...