3

データ収集プロジェクト用に Java でサーバー側プログラムを開発しようとしています。

アーキテクチャは次のとおりです。

定期的にデータを収集してサーバーに送り返すリモート電子デバイスがあります。このデバイスには、GPRS 接続が有効になっている SIM カードが装備されているため、インターネットにアクセスできるコンピューターと見なすことができます。データをサーバーに送り返す前に、サーバーの IP アドレスを知る必要があります。

ISP 経由で静的 IP を取得するには費用がかかりすぎるため、動的 DNS (DDNS) を試すことにしました。PC に DDNS クライアントをインストールし、ルーターのポート転送を次のように構成しました。

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.

次に、単純なサーバー/クライアント プログラムを自分の PC で実行しようとしました (両方とも同じ PC 上にあります)。DataInputStream複雑なことは何もせず、 andDataOutputStreamクラスを使用していくつかの文字列を送受信するだけです。

クライアントはサーバーに接続でき、サーバーは接続を受け入れることができます (ポート転送は機能しますか?!)。しかし、データの読み取りまたは送信を試みると、どちらも IOException をスローします。サーバーが言いConnection reset、数秒後、クライアントはtimeout.

サーバーが新しい接続を受け入れると、ポート転送設定で指定されていない任意の新しいポート番号を選択するようですが、それは問題ですか?

IOException の実際の原因、データの読み取りまたは書き込みができない理由、および問題を解決するための提案を知りたいですか?

どうもありがとう。

サーバーのコード:

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();
      }
   }
}

クライアントのコード: xxxxxxx.xicp.netは私の無料のドメイン名であり、サーバーはポートをリッスンします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();
      }
   }
}
4

2 に答える 2

0

私の推測: ルーターで NAT を構成したので、すべての着信接続は PC のポート 33333 に転送されます。クライアントがサーバーに接続されると、サーバーと通信するために別のポート (例: 5000) が選択されます。サーバーがクライアントに何かを送信しようとすると、ポート 5000 に送信されます。NAT 設定ではポート 5000 が転送されないため、送信は失敗します。よくわかりません、テストする必要があります。

わかりました、確認されました。携帯電話の 3G 接続を使用してラップトップでクライアントを実行し、ルーターに接続されたデスクトップ PC でサーバーを実行しようとしました。ポート 33333 はデスクトップ PC に転送されます。今では完全に機能します。

于 2013-11-14T15:23:52.003 に答える
0

これは少し前のことですが、最初は接続にも同じ問題がありました。

問題は、DataOuputStream/DataInputStream フローを閉じることから生じます。基本的に、それらを開いたままにして、書き込みが完了したらフラッシュを呼び出す必要があります。

ただし、送信されたよりも多くのバイトを読み取ろうとすると、どちらの接続でも問題になる可能性があります。メッセージ「ヘッダー」をコード (センチネルとも呼ばれます) にスローして、受信側に読み取るバイト数を通知することをお勧めします。

また、迅速なデータ トラバーサルについては、BufferedOutputStream/BufferedInputStream を試してください。速度の向上は信じられないほどです。

于 2014-05-31T21:27:04.727 に答える