Pregunta

I'm trying to develop a server side program in Java for a data collection project.

Here's the architecture:

I have a remote electronic device which collects data periodically and sends it back to the server. This device is equipped with a SIM card which has GPRS connection activated, so it can be considered as a computer with internet access. Before sending data back to the server, it has to know the IP address of the server.

As it's too expensive to have a static IP via my ISP, I've then decided to try dynamic DNS(DDNS). I've installed the DDNS client on my PC and configured the port forwarding in my router as follows:

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.

Then I've tried to run a simple server/client program on my PC (Yeah, both of them on the same PC). They do nothing complicated, just sending and receiving some strings using DataInputStream and DataOutputStream class.

The client can connect to the server, and the server can accept the connection (port forwarding works ?!). But when they try to read or send data, both of them throw an IOException. The server says Connection reset and a few seconds later, the client gets timeout.

It seems that when the server accepts a new connection, they will pick an arbitrary new port number which is not specified in port forwarding settings, is it the problem ?

I'd like to know what's the actual cause of the IOException, why they cannot read or write data, and any suggestion for fixing the issue ?

Thanks a lot.

Code of server:

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 of client: xxxxxxx.xicp.net is my free domain name, and the server listens to 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();
      }
   }
}
¿Fue útil?

Solución

My guess: I've NAT configured in my router, so all incoming connection is forwarded to the port 33333 of my PC. Once the client is connected to the server, it will pick an other port, e.g. 5000, to communicate with the server. When the server tries to send something to the client, it sends it to port 5000. AS in NAT setting the port 5000 is not forwarded, the transmission fails. I'm not sure, need to be tested.

Ok, it's confirmed. I've tried to run the client on my laptop using a my phone's 3G connection, and the server on my desktop PCconnected to the router. The port 33333 is forworded to the desktop PC. Now it works perfectly.

Otros consejos

I know this was a while ago, but I have/had the same problem with my connections at first too.

Your problem stems from closing your DataOuputStream/DataInputStream flows. Basically you want to keep them open and when done writing call flush.

This could be problematic for the either connection however, if you try to read more bytes than have been sent. I suggest throwing an message 'header' into your code (also called a sentinel) to tell the receiving party how many bytes it will read.

Also for quick data traversal try BufferedOutputStream/BufferedInputStream, the speed increase is incredible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top