简体   繁体   English

系统中的两个不同的 UDP 套接字可以绑定同一个端口吗?

[英]Can two different UDP socket in a system bind same port?

I have an application which uses UDP connection, now when i try to run the app more than once its throwing me an exception我有一个使用 UDP 连接的应用程序,现在当我尝试多次运行该应用程序时,它向我抛出异常

java.net.BindException: Address already in use: Cannot bind

but in my another app, which uses tcp connection, i can open two instance of the same app and its working fine.但是在我的另一个使用 tcp 连接的应用程序中,我可以打开同一个应用程序的两个实例并且它工作正常。 why this error only with UDP connection?为什么此错误仅与 UDP 连接有关?

Edit:编辑:

TCP socket:

Socket clientSocket= new Socket(ipAddress, 8000);
Socket clientSocket1= new Socket(ipAddress, 8000);

If i create TCP socket like above,with same port, it is not throwing any error.如果我像上面那样创建 TCP 套接字,使用相同的端口,它不会抛出任何错误。 but if i do this with UDP Socket it throwing me an exception, why?但是如果我用 UDP Socket 来做这件事,它会抛出一个异常,为什么?

It has to do with the difference between TCP and UDP.它与 TCP 和 UDP 之间的区别有关。 When you create a TCP socket you are creating a synchronous client connection to the port on another machine, and when you connect to an address you actually get a local port on the socket as well.当您创建 TCP 套接字时,您正在创建到另一台机器上的端口的同步客户端连接,并且当您连接到一个地址时,您实际上也在套接字上获得了一个本地端口。 So in your example code the two sockets created might be因此,在您的示例代码中,创建的两个套接字可能是

clientSocket = localhost:2649 <-> ipAddress:8000
clientSocket1 = localhost:2650 <-> ipAddress:8000

Note that while they remote address is the same, the local address has different ports, which is why this is allowed.请注意,虽然它们的远程地址相同,但本地地址具有不同的端口,这就是允许的原因。 So here the local an remote machines can reliably send the data back and forth using the established ports.所以在这里本地和远程机器可以使用已建立的端口可靠地来回发送数据。

For UDP this is not the case (I am assuming you are using DatagramSocket).对于 UDP,情况并非如此(我假设您使用的是 DatagramSocket)。 Since UDP is asynchronous (as opposed to synchronous like TCP), to recieve data you are not creating a binding to another specific machine, so for example if you were to try由于 UDP 是异步的(而不是像 TCP 那样的同步),为了接收数据,您不会创建到另一台特定机器的绑定,例如,如果您要尝试

DatagramSocket udp1 = new DatagramSocket(8000); // = localhost:8000 <-> ?
DatagramSocket udp2 = new DatagramSocket(8000); // = localhost:8000 <-> ?

the udp socket does not know where the data is coming from so there can not be a unique mapping like TCP, also unlike TCP the port you specify is your machine's port, not a remote machine port . udp 套接字不知道数据来自哪里,因此不能像 TCP那样有唯一的映射,而且与 TCP 不同的是,您指定的端口是您机器的端口,而不是远程机器端口

Another way to think of it when you create a UDP socket it is like creating a TCP server socket.当您创建 UDP 套接字时,另一种思考方式就像创建一个 TCP 服务器套接字。 When you create a TCP server socket it is waiting for a connection to come from some machine but that machine is unknown and when you create a TCP server socket the port you specify is a local port:当您创建 TCP 服务器套接字时,它正在等待来自某台机器的连接,但该机器未知,当您创建 TCP 服务器套接字时,您指定的端口是本地端口:

ServerSocket ss1 = new ServerSocket(8000); // = localhost:8000 <-> ?
ServerSocket ss2 = new ServerSocket(8000); // = localhost:8000 <-> ?

Again like UDP this will create a bind exception because the port is for the local machine and the mappings are no longer unique.再次像 UDP 一样,这将创建绑定异常,因为端口用于本地机器并且映射不再唯一。 But when you accept a connection on a server socket the remote machine comes into play to make the socket unique, just as when you create a Socket to a remote machine:但是,当您接受服务器套接字上的连接时,远程机器会发挥作用以使套接字唯一,就像您创建到远程机器的 Socket 一样:

Socket s1 = ss1.accept();// localhost:8000 <-> remoteIp1:12345
Socket s2 = ss1.accept();// localhost:8000 <-> remoteIp2:54321

Note that although the local address is the same, the remote addresses for the sockets are different, and hence the total mapping (localip:port<->remoteip:port) is now unique.请注意,虽然本地地址相同,但套接字的远程地址不同,因此总映射 (localip:port<->remoteip:port) 现在是唯一的。

So in a way you can think of a UDP socket as kind of like a TCP server socket and that is why you have to bind it to a unique port.因此,在某种程度上,您可以将 UDP 套接字视为有点像 TCP 服务器套接字,这就是您必须将其绑定到唯一端口的原因。

Are you sure that the TCP application really does a bind with a non-zero port number?您确定 TCP 应用程序确实使用非零端口号进行绑定吗? It shouldn't work for TCP either.它也不应该适用于 TCP。 The purpose of port numbers is to identify which running application instance to route the traffic to;端口号的目的是确定将流量路由到哪个正在运行的应用程序实例; if two applications were to each bind two sockets to the same port number, that routing becomes impossible, which is why it's an error.如果两个应用程序分别将两个套接字绑定到同一个端口号,那么路由就变得不可能,这就是错误的原因。

You have to set the socket to be shareable, or as it's called, SO_REUSEPORT.您必须将套接字设置为可共享的,或称为 SO_REUSEPORT。

In C or C++ this is done with the setsockopt function.在 C 或 C++ 中,这是通过 setsockopt 函数完成的。 When you bind to a port, then set the SO_REUSEPORT, another process can also bind a socket to the same port number.当你绑定到一个端口,然后设置SO_REUSEPORT,另一个进程也可以绑定一个socket到同一个端口号。 An example use for this is multi-process applications, using multiple CPU cores to read incoming data as fast as possible.一个例子是多进程应用程序,使用多个 CPU 内核尽可能快地读取传入的数据。 When this is done the traffic is load balanced amongst the processes, or as is more likely the case, the first one to read the data, gets it (With UDP).完成此操作后,流量在进程之间进行负载平衡,或者更有可能的是,第一个读取数据的人获取它(使用 UDP)。

With TCP this is only relevant to a new connection coming in. When a new connection comes in, the first process to accept() the connection owns that connection, but the port number is still shared by all the processes who bound to it and new connections are subsequently handed off to the first one who grabs it with accept().对于 TCP,这仅与进入的新连接相关。当新连接进入时,第一个接受()连接的进程拥有该连接,但端口号仍由绑定到它的所有进程共享,并且新的随后将连接移交给第一个使用 accept() 获取它的人。 It makes no sense to share READING from a TCP socket (though multi-threaded apps can do this) as the data is coming in as a stream with no record delimiters, so having multiple readers read it is just, well, an analogy would be, multiple people reading the same book and tearing out the pages as they read them.从 TCP 套接字共享 READING 是没有意义的(尽管多线程应用程序可以这样做),因为数据是作为没​​有记录分隔符的流传入的,所以让多个读者读取它只是,好,一个类比,多人阅读同一本书并在阅读时撕掉书页。 You'd be left with each reader having an incoherent mess.你会留下每个读者都有一个语无伦次的混乱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 两个不同的套接字实例可以侦听相同的TCP端口(端口已在使用中) - Can two different socket instances listen to same TCP port ( Port already in use ) 无法使用相同的端口和不同的IP迭代和绑定套接字 - Cant iterate and bind socket with same port and different IPs 两个线程可以在同一个端口中调用一个新的套接字(客户端套接字)吗? - Can two threads call a new socket (client socket) in the same port? 两个具有相同端口和地址的套接字实例 - two instance of socket with same port and address Java:从同一UDP端口重复发送或为UDP Socket.send()指定本地端口 - Java: send repeatedly from same UDP port or specify localport for UDP Socket.send() 如何在两个单独的程序上将两个套接字绑定到同一端口? - How can I bind two sockets to the same port on two separate programs? 在udp套接字上设置源端口 - Setting source port on udp socket 我可以使用两个不同的线程在同一个套接字上读写吗? - Can I read and write on the same socket using two different threads? 用两个线程创建到同一端口的两个套接字连接是否合法 - is it legal to create two socket connection to same port with two threads 使用Java DatagramSockets,我可以将两个不同的套接字连接到同一本地端口但在不同的本地地址吗? - With Java DatagramSockets, can I connect two different sockets to the same local port but on different local addresses?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM