2010-05-05 34 views
7

Tôi có một ứng dụng mà sử dụng kết nối UDP, bây giờ khi tôi cố gắng để chạy các ứng dụng nhiều hơn một lần nó ném cho tôi một ngoại lệCó thể hai ổ cắm UDP khác nhau trong một hệ thống kết nối cùng một cổng không?

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

nhưng trong ứng dụng khác của tôi, trong đó sử dụng kết nối tcp, tôi có thể mở hai dụ của cùng một ứng dụng và hoạt động tốt. tại sao lỗi này chỉ với kết nối UDP?

Edit:

TCP socket: 

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

Nếu tôi tạo socket TCP như trên, với cùng một cổng, nó không phải là ném bất kỳ lỗi. nhưng nếu tôi làm điều này với UDP Socket nó ném cho tôi một ngoại lệ, tại sao?

Trả lời

1

Kiến thức của tôi bằng cách sử dụng bind() với cùng số cổng trên nhiều ổ cắm không xác định. Trên UDP không có cơ chế kết nối cơ bản như với TCP. Điều này có nghĩa rằng mặc dù bạn đã gửi một gói tin đến một địa chỉ IP cụ thể trên một trong các ổ cắm nó không thay đổi bất cứ điều gì về trạng thái của ổ cắm của bạn

+0

vì vậy, bạn có nghĩa là chúng tôi không thể tạo hai ổ cắm udp với cùng một cổng? – swift

1

Bạn có chắc chắn rằng ứng dụng TCP thực sự liên kết với một không số cổng không? Nó cũng không hoạt động với TCP. Mục đích của số cổng là xác định cá thể ứng dụng đang chạy nào để định tuyến lưu lượng truy cập đến; nếu hai ứng dụng đã từng liên kết hai ổ cắm với cùng một số cổng, việc định tuyến đó trở thành không thể, đó là lý do tại sao đó là lỗi.

13

Nó có liên quan đến sự khác biệt giữa TCP và UDP. Khi bạn tạo một ổ cắm TCP, bạn đang tạo một kết nối máy khách đồng bộ đến cổng trên một máy khác và khi bạn kết nối với một địa chỉ, bạn cũng thực sự có một cổng cục bộ trên ổ cắm. Vì vậy, trong mã ví dụ của bạn, hai ổ cắm được tạo có thể là

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

Lưu ý rằng khi địa chỉ ở xa giống nhau, địa chỉ cục bộ có các cổng khác nhau, đó là lý do tại sao điều này được cho phép. Vì vậy, ở đây một máy từ xa địa phương có thể gửi dữ liệu một cách đáng tin cậy bằng cách sử dụng các cổng đã thiết lập.

Đối với UDP, đây không phải là trường hợp (Tôi giả sử bạn đang sử dụng DatagramSocket). Kể từ UDP là không đồng bộ (như trái ngược với đồng bộ như TCP), để nhận dữ liệu bạn đang không tạo ra một liên kết đến một máy cụ thể, ví dụ như vậy nếu bạn đã cố gắng

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

socket UDP không biết nơi dữ liệu đến từ vì vậy không thể có một ánh xạ duy nhất như TCP, cũng như không giống như TCP cổng bạn chỉ định là cổng của máy, chứ không phải cổng máy từ xa.

Một cách khác để nghĩ về nó khi bạn tạo một ổ cắm UDP, nó giống như việc tạo một ổ cắm máy chủ TCP. Khi bạn tạo một ổ cắm máy chủ TCP nó đang chờ đợi một kết nối đến từ một số máy nhưng máy đó là không rõ và khi bạn tạo một ổ cắm máy chủ TCP cổng mà bạn chỉ định là một cảng địa phương:

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

Again như UDP điều này sẽ tạo ra một ngoại lệ ràng buộc vì cổng dành cho máy cục bộ và ánh xạ không còn là duy nhất nữa.Nhưng khi bạn chấp nhận một kết nối vào một ổ cắm máy chủ máy từ xa đến chơi để làm cho ổ cắm độc đáo, cũng giống như khi bạn tạo một Socket đến một máy từ xa:

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

Lưu ý rằng mặc dù các địa chỉ cục bộ là như nhau , các địa chỉ từ xa cho các socket là khác nhau, và do đó tổng ánh xạ (localip: port < -> remoteip: port) giờ đây là duy nhất.

Vì vậy, theo cách bạn có thể nghĩ về một ổ cắm UDP giống như một ổ cắm máy chủ TCP và đó là lý do tại sao bạn phải liên kết nó với một cổng duy nhất.

Các vấn đề liên quan