Byte side: Can TCP and UDP use the same port number?
First the answer: yes. How to understand it?
I think this issue starts with computer network communications. Students who have studied computer networks may still remember the 7-layer or 4-layer network model. TCP/UDP belongs to the transport layer protocol. Below the transport layer is the network layer. The network layer mainly communicates through the IP protocol. This is also the lowest level that we can touch in daily program development. The data link layer and physical layer below are not what ordinary programmers like us need to care about.
picture
IP
Let’s look at the network layer in detail first. At the IP network layer, when the sender transmits data to the recipient, it first needs to know the recipient's IP address. The IP address can uniquely identify a computer in the network, and then the data can reach the recipient's computer according to the IP protocol. , but there are dozens of programs running on the computer where the recipient is located. Which program should the computer give this data to?
The port number
It's like a courier arriving at a building. How does it deliver the courier to the corresponding user next? If you are smart, you must have thought of it, that is the house number.
In a computer, the port number is the house number. The computer's operating system can bind different port numbers to different programs. In this way, when the sender sends data, it not only needs to set the receiver's IP, but also adds the receiver's port number, so that the computer where the receiver is located can send the data. Forwarded to the correct program.
TCP/UDP
So can TCP and UDP use the same port number? In fact, there is a transport layer protocol processing process before looking up the port number. After the operating system receives the data, it will first check whether the data packet uses the TCP protocol or the UDP protocol, and then perform different parsing processes according to the protocol to extract the data. Then, forward it to the program with the corresponding port.
Therefore, TCP and UDP can use the same port number, which is also common in reality. For example, DNS (Domain Name System) may need to support both TCP and UDP queries. Both queries can be received and responded to through the standard port 53.
But under the same transmission protocol, the port numbers cannot be the same. If they are the same, the operating system's protocol stack will not know which program to forward this data packet to, and this design will add a lot of trouble.
Some students may have observed a phenomenon, that is, multiple websites on the same computer can share port 80 or 443. This is actually the capability of the application layer. These websites are all hosted on the same Web server program. This Web server The program is bound to port 80. After the web server receives the data, it forwards it to different website programs based on the host header (can be understood as a domain name) in the HTTP protocol.
Also, if you have multiple IPs on your computer, there will be no problem. Different IPs represent different network interfaces. Even if they both use the TCP protocol, as long as the IPs are different and the port numbers are the same, there will be no conflict at all.
"IP + transport layer protocol + port number" is what we often call a socket, which ensures that data is passed from one network program to another. If you use TCP and UDP programming directly, you need to manually set these parameters for the socket.
Example
There is no proof for what I say, so I will write a demo for everyone, using the Go language, which is simple and easy to understand:
The following program will start a TCP server and a UDP server, which are bound to the same IP and port number. For the convenience of testing, the local IP of 127.0.0.1 is used here. You can also change it to a LAN or public 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]))
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- twenty one.
- twenty two.
- twenty three.
- twenty four.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
Then create two more clients, one is the TCP client:
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")
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- twenty one.
- twenty two.
- twenty three.
- twenty four.
- 25.
The other is a UDP client:
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")
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- twenty one.
- twenty two.
- twenty three.
- twenty four.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
We can see that the client uses the target address localhost:12345 when making requests. The localhost is actually a domain name, which will be resolved to 127.0.0.1 by the local computer. If you are unclear about this, you can read this article I wrote before:
The actual operating effect is as follows:
picture
Finally, to summarize: In network communication, in the same computer, the TCP and UDP protocols can use the same port number. The socket address in each network process is unique and identified by a triplet (IP address, transport layer protocol, port number). The operating system will correctly deliver the received data to the corresponding application based on the transport layer protocol (TCP or UDP) and port number in the data packet.