2015-09-04 26 views
0

我希望我的客戶端應用程序是能夠將連接到服務器應用程序。Java廣播:拋出BindException

問題是我的客戶端不知道服務器ip(在局域網內)

所以我嘗試使用java對象MulticastSocket。幸運的是,Oracle有一個example of Broadcasting的頁面。

這裏我已經重新安排了它供我使用。

Server代碼:

long FIVE_SECONDS = 5000;   
int port = 4445; 

DatagramSocket socket = new DatagramSocket(port); 

while (true) { 
    System.out.println("Server running..."); 
    try { 
     // message for client 
     String dString = "Hello Client";     
     byte[] buf = dString.getBytes(); 

     // send 
     InetAddress group = InetAddress.getByName("230.0.0.1"); 
     DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port); 
     socket.send(packet); 

     // sleep for a while 
     try { 
      Thread.sleep((long)(Math.random() * FIVE_SECONDS)); 
     } 
     catch (InterruptedException e) { 
      System.err.println("Interrupted Exception"); 
     } 
    } catch (IOException e) { 
     System.err.println("IOException"); 
    } 
} 

客戶端代碼:

MulticastSocket socket = new MulticastSocket(4445); 
InetAddress address = InetAddress.getByName("230.0.0.1"); 
socket.joinGroup(address); 

// receive the message 
byte[] buf = new byte[256]; 
DatagramPacket packet = new DatagramPacket(buf, buf.length); 
socket.receive(packet); 

String received = new String(packet.getData(), 0, packet.getLength()); 
System.out.println("Received: " + received); 

socket.leaveGroup(address); 
socket.close(); 

當我Srver運行:沒有問題,但是當我嘗試運行的客戶端扔java.net.BindException: Address already in use原因客戶端和服務器正在偵聽/發有關port 4445的信息。

但是不是這樣嗎? 要彼此連接,他們必須具有相同的端口號,否則他們將永遠不會'遇見'

我可以解決這個問題嗎?怎麼樣?

端口號是否正確?

這是一個正確的解決有關未知服務器IP的問題?

謝謝!

+0

雖然我不能提出這個問題,但同一端口上的兩個偵聽器將無法工作。一個端口就像一個IO流,當有兩個編寫者/讀者時,就會發生不好的事情。這就是爲什麼拋出一個'BindException'來防止壞事發生的原因。 – WorldSEnder

+0

@WorldSEnder:可能你說得對,但是在我的問題(和[這裏](https://docs.oracle.com/javase/tutorial/networking/datagrams/broadcasting.html))中鏈接到Oracle的例子中,他們使用相同的端口號... – xdola

+0

你是否運行過他們的例子?如果否,您是否在同一臺計算機上使用您的客戶端和服務器?如果是,那麼我可以解釋這個問題,如果沒有我不知道 – WorldSEnder

回答

3

正如沃倫在他的回答中提到的,您的客戶端和服務器無法綁定到同一臺計算機上的同一端口。 Oracle示例沒有這樣做。

客戶端應該綁定到端口4446和服務器應該綁定到端口4445.當服務器創建一個DatagramPacket它應該是4446.

如果你這樣做客戶端的端口和客戶端這樣做仍然無法接收,您可能需要在服務器上設置多播的傳出接口。您可以使用setInterfacesetNetworkInterface方法執行此操作。

例如,假設您的服務器的IP地址爲192.168.1.1和192.168.2.1。如果你想讓你的發送者從192.168.1.1發送,你可以撥打:

multicastSocket.setInterface(InetAddress.getByName("192.168.1.1")); 
1

由於您試圖在同一臺計算機上運行服務器應用程序和您的客戶端應用程序,因此您會收到此異常。當你啓動你的客戶端時,你的服務器已經綁定到端口4445,所以當你的客戶端試圖綁定到它時,它已經被使用 - 因此不可用。

在不同的機器上運行你的服務器和你的客戶端會繞過那個特定的錯誤。但是,您也可以通過爲您的服務器和客戶端選擇不同的端口來避開它。

例如,如果您在端口4445上運行服務器,並在端口4446上運行您的客戶端,則可以執行以下操作。在服務器上,你會添加一個變量客戶端端口,使用客戶端端口作爲目標端口發送您的DatagramPacket時:

int clientPort = 4446; 
... 
DatagramPacket packet = new DatagramPacket(buf, buf.length, group, clientPort); 

,而不是

DatagramPacket packet = new DatagramPacket(buf, buf.length, group, port); 

在客戶端,你會簡單地綁定到客戶端,而不是服務器端口:

MulticastSocket socket = new MulticastSocket(4446); 

,而不是

MulticastSocket socket = new MulticastSocket(4445); 

爲服務器和客戶端使用不同的端口號將允許您在同一臺計算機上運行服務器應用程序和客戶端應用程序,並讓您通過此特定問題。

+0

感謝您的回答,但是,您的更改不能解決問題:在同一臺機器上,客戶端無法找到服務器的數據包。 – xdola