2016-01-27 17 views
0

我創建了一個將在我的桌面上運行的服務器,用於發送和接收來自客戶端的消息。客戶端應用程序將在android上運行。到目前爲止,這兩個程序都啓動了,客戶端可以將初始連接發送到服務器。我的桌面通過路由器連接到互聯網,我有端口從路由器轉發接收信息。DatagramSocket數據包IPAddress被路由器更改了嗎?

服務器能夠接收客戶端發送的所有消息。但是,服務器無法響應。我對接收到的數據包(服務器端)做了一個快速檢查,並且它說該數據包的IP地址是我的路由器的IP地址。這是否意味着我將無法發送迴應,因爲我的所有數據包都將其IP更改爲路由器的本地地址(因爲端口轉發)?

我發佈了下面的一些代碼,雖然我不知道它會有所幫助。非常感謝您的意見。

服務器:

public class QuoteServerThread extends Thread { 

protected DatagramSocket socket = null; 
DatagramPacket dgp = null; 
protected boolean running = true; 
ArrayList<ConnectedUser> users = new ArrayList<>(); 
String state; 
int port; 
int userId; 

public QuoteServerThread(String name, String state) throws IOException { 
    super(name); 
    port = 4445; 
    userId = 1; 
    socket = new DatagramSocket(port); 
    this.state = state; 
    this.state = "listening"; 
    System.out.println("Server Socket is now listening on port: " + port); 
} 

public void run() { 
    while (running) { 
     try { 
      byte[] buf = new byte[256]; 

      // receive request 
      final DatagramPacket packet = new DatagramPacket(buf, buf.length); 
      socket.receive(packet); 
      if(packet.getData() == null){ 
       System.out.println(packet.getData()); 
       return; 
      } 
      else{ 
       System.out.println(packet.getData()); 
      } 
      dgp = packet; 
      String message = new String(packet.getData(), 0, packet.getLength()); 

      if(state.equals("listening")) { 
       if(message.contains("newUser")){ 
        ConnectedUser newUser = new ConnectedUser(userId, socket); 
        users.add(newUser); 
        System.out.println("connected users: " + users.size()); 

        String msg = "ID/" + userId; 

        InetAddress IPAddress = packet.getAddress(); 
        int _port = packet.getPort(); 
        System.out.println(IPAddress + "," + _port); 
        DatagramPacket out = new DatagramPacket(msg.getBytes(), msg.length(), IPAddress, _port); 
        socket.send(out); 

        userId++; 
       } 
       else if(message.contains("ID/")){ 
        String receivedMessage[] = message.split("/"); 

        System.out.println(receivedMessage[0] + ", " + receivedMessage[1] + ", " + receivedMessage[2]); 
       } 
       else{ 
        System.out.println(message); 
       } 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
      running = false; 
     } 
    } 
    socket.close(); 
} 

}

客戶:

public class QuoteServerThread extends Thread { 

protected DatagramSocket socket = null; 
protected boolean running = true; 
TextView chatWindow; 
TextView notification; 
EditText chatBox; 
MainActivity ma; 
ScrollView sv; 

public QuoteServerThread(MainActivity ma, TextView chatWindow, EditText chatBox, ScrollView sv, TextView notification) throws IOException { 
    this("QuoteServerThread"); 
    this.ma = ma; 
    this.chatWindow = chatWindow; 
    this.sv = sv; 
    this.chatBox = chatBox; 
    this.notification = notification; 
} 

public QuoteServerThread(String name) throws IOException { 
    super(name); 
    socket = new DatagramSocket(); 
} 

public void run() { 
    while (running) { 
     try { 
      byte[] buf = new byte[256]; 

      // receive request 
      final DatagramPacket packet = new DatagramPacket(buf, buf.length); 
      socket.receive(packet); 

      if(packet.getData() == null){ 
       System.out.println("data was null!"); 
       return; 
      } 

      String message = new String(packet.getData(), 0, packet.getLength()); 

      final String notif = message; 
      notification.post(new Runnable() { 
       public void run() { 
        notification.setText("server " + "__msg: " + notif); 
       } 
      }); 


      if(ma.state.equals("connected")) { 
       final String chatText = chatWindow.getText().toString() + "\n" + "Sender: " + message; 
       chatWindow.post(new Runnable() { 
        public void run() { 
         chatWindow.setText(chatText); 
         sv.post(new Runnable() { 
          public void run() { 
           sv.fullScroll(View.FOCUS_DOWN); 
           chatBox.post(new Runnable() { 
            public void run() { 
             chatBox.requestFocus(); 
            } 
           }); 
          } 
         }); 
        } 
       }); 
      } 
      else if(ma.state.equals("waitingconnection")){ 
       String msgSplit[]; 
       if(message.contains("ID/")){ 
        msgSplit = message.split("/"); 

        final String id = msgSplit[1]; 
        ma.clientID = Integer.getInteger(id); 


        notification.post(new Runnable() { 
         public void run() { 
          notification.setText("connected to server " + "__msg: " + id); 
          ma.state = "connected"; 
         } 
        }); 
       } 
      } 

     } catch (IOException e) { 
      e.printStackTrace(); 
      running = false; 
     } 
    } 
    socket.close(); 
} 

}

這裏唯一的問題是,沒有收到一個響應客戶端。再次聲明問題,我相信我的路由器上的端口轉發正在將數據包地址更改爲其本地ipaddress(我的電話正在從移動網絡發送)。關於如何解決這個問題的任何想法?

+0

我可能在我的許多測試中發現錯誤。如果我知道明天我會更新這個帖子的答案。 – Mishtiff

回答

0

上面的問題是由於我在後臺運行的代碼。發送消息時,我使用了一個名爲MsgSender的類。但是,MsgSender正在創建一個新套接字併發送數據。數據發送後,它關閉套接字,不再監聽服務器的響應。

爲了解決這個問題,我共享了打開的套接字,並通過單個套接字發送所有數據,以便它可以偵聽返回的任何信息。

確保當您發送信息時,如果您需要偵聽響應,您必須通過它發送的套接字進行偵聽。如果您不需要偵聽您將要發送的數據的響應,則可以關閉套接字。

0

我想你會看到網絡地址轉換(NAT)和端口轉發的效果。從Android客戶端的角度來看,它與您的路由器進行通信。然後,您的路由器而不是處理消息本身將處理卸載到您的服務器(端口轉發)。

在您的服務器上,您會看到目標地址。由於您的Android客戶端正在與您的路由器通話,因此您看到的目標IP地址就是您的路由器的IP地址。

如果你想回復,你應該採取的數據報的源地址,並將答覆發回該地址。當數據報將通過NAT傳遞路由器時,它會將源地址更改爲路由器的源地址。