Socket serveur Java avec NAT et DNS dynamique


J'essaie de développer un programme côté serveur en Java pour un projet de collecte de données.

Voici l'architecture:

J'ai un appareil électronique distant qui collecte des données périodiquement et les renvoie au serveur. Cet appareil est équipé d'une carte SIM qui a une connexion GPRS activée, il peut donc être considéré comme un ordinateur avec accès Internet. Avant d'envoyer des données au serveur, il doit connaître l'adresse IP du serveur.

Car c'est trop cher pour avoir une adresse IP statique via mon FAI, j'ai alors décidé d'essayer le DNS dynamique(DDNS). J'ai installé le client DDNS sur mon PC et configuré la redirection de port dans mon routeur comme suit:

External Port Start: 33333
External Port End: 33333
Protocol: TCP
Internal Port Start: 33333
Internal Port End: 33333
Server IP Address: 192.168.0.100 // My PC's IP Adress.

Ensuite, j'ai essayé d'exécuter un simple programme serveur/client sur mon PC (Ouais, les deux sur le même PC). Ils ne font rien de compliqué, envoyant et recevant simplement des chaînes en utilisant la classe DataInputStream et DataOutputStream.

, Le client peut se connecter au serveur, et le serveur peut accepter la connexion (port le transfert fonctionne ?!). Mais quand ils essaient de lire ou d'envoyer des données, les deux lancent une IOException. Le serveur dit - Connection reset, et quelques secondes plus tard, le client obtient timeout.

Il semble que lorsque le serveur accepte une nouvelle connexion, il choisira un nouveau numéro de port arbitraire qui n'est pas spécifié dans les paramètres de redirection de port, est-ce le problème ?

J'aimerais savoir quelle est la cause réelle de l'IOException, pourquoi ils ne peuvent pas lire ou écrire des données, et toute suggestion pour réparer le question ?

Merci beaucoup.

Le Code du serveur:

import java.net.*;
import java.io.*;

public class GreetingServer extends Thread
{
   private ServerSocket serverSocket;

   public GreetingServer(int port) throws IOException
   {
      serverSocket = new ServerSocket(port);
   }

   public void run()
   {
      while(true)
      {
         try
         {
            System.out.println("Waiting for client on port " +
            serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            System.out.println("Just connected to "
                  + server.getRemoteSocketAddress());
            DataInputStream in =
                  new DataInputStream(server.getInputStream());
            System.out.println(in.readUTF());
            DataOutputStream out =
                 new DataOutputStream(server.getOutputStream());
            out.writeUTF("Thank you for connecting to "
              + server.getLocalSocketAddress() + "\nGoodbye!");
            server.close();
         }catch(SocketTimeoutException s)
         {
            System.out.println("Socket timed out!");
            break;
         }catch(IOException e)
         {
            e.printStackTrace();
            break;
         }
      }
   }
   public static void main(String [] args)
   {
      int port = 33333;
      try
      {
         Thread t = new GreetingServer(port);
         t.start();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

Code du client: xxxxxxx.xicp.net est mon nom de domaine gratuit, et le serveur écoute le port 33333.

import java.net.*;
import java.io.*;

public class GreetingClient
{
   public static void main(String [] args)
   {
      InetAddress ip;
      String serverName;
      int port = 33333;
      try
      {
         ip = InetAddress.getByName("xxxxxxx.xicp.net");
         serverName = ip.getHostAddress();
         System.out.println("Connecting to " + serverName
                             + " on port " + port);
         Socket client = new Socket(ip, port);
         System.out.println("Just connected to "
                      + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out =
                       new DataOutputStream(outToServer);

         out.writeUTF("Hello from "
                      + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in =
                        new DataInputStream(inFromServer);
         System.out.println("Server says " + in.readUTF());
         client.close();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}
Author: vesontio, 2013-11-11

2 answers

Ma supposition: J'ai NAT configuré dans mon routeur, donc toute connexion entrante est transmise au port 33333 de mon PC. Une fois que le client est connecté au serveur, il choisira un autre port, par exemple 5000, pour communiquer avec le serveur. Lorsque le serveur essaie d'envoyer quelque chose au client, il l'envoie au port 5000. COMME dans la configuration NAT le port 5000 n'est pas transféré, le la transmission échoue. Je ne suis pas sûr, besoin d'être testé.

Ok, c'est confirmé. J'ai essayé d'exécuter la client sur mon ordinateur portable à l'aide d'une connexion 3G de mon téléphone, et le serveur sur mon PC de bureauconnecté au routeur. Le port 33333 est forworded au PC de bureau. Maintenant, cela fonctionne parfaitement.

 0
Author: vesontio, 2013-11-14 15:23:52

Je sais que c'était il y a un moment, mais j'ai/eu le même problème avec mes connexions au début aussi.

Votre problème provient de la fermeture de vos flux DataOuputStream/DataInputStream. Fondamentalement, vous voulez les garder ouverts et une fois l'écriture terminée, appelez flush.

Cela pourrait cependant être problématique pour l'une ou l'autre connexion, si vous essayez de lire plus d'octets que ceux qui ont été envoyés. Je suggère de lancer un message "en-tête" dans votre code (également appelé sentinelle) pour dire à la partie destinataire comment beaucoup d'octets qu'il lira.

Également pour la traversée rapide des données, essayez BufferedOutputStream/BufferedInputStream, l'augmentation de la vitesse est incroyable.

 0
Author: Chris Sullivan, 2014-06-23 15:59:56