2012-01-22 15 views
2

私はホームサーバーで実行するJavaプログラムを持っています。私はまた、サーバーにメッセージを送信し、ソケットを使用して応答を受け取るJavaクライアントプログラムを持っています。Javaソケット通信 - 速度の向上

私はそれをうまく実装しましたが、少し遅くなり、できるだけ早くそれを取得しようとしています。ここで

は私のコードです:

サーバー

public class Server implements Runnable{ 
    static ServerSocket socket1; 
    protected final static int port = 4701; 
    static Socket connection; 
    static StringBuffer process; 

private String handleRequest(String req){ 
    if(req.equals("marco")){ 
     return "polo"; 
    }else 
     return "null"; 

} 

public void run(){ 
    try { 
     socket1 = new ServerSocket(port); 
     int character; 

     while (true) { 
      connection = socket1.accept(); 

      BufferedInputStream is = new BufferedInputStream(connection.getInputStream()); 
      InputStreamReader isr = new InputStreamReader(is); 
      process = new StringBuffer(); 
      while ((character = isr.read()) != 13) { 
       process.append((char) character); 
      } 
      String returnCode = handleRequest(process.toString()) + (char) 13; 
      BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream()); 
      OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII"); 
      osw.write(returnCode); 
      osw.flush(); 
     } 
    } catch (IOException e) { 
     System.out.println("error starting server " + e.getMessage()); 
    } 
    try { 
     if(connection != null) 
      connection.close(); 

    } catch (IOException e) { 
    } 

クライアント

String host = "xx.xx.xx.xxx"; 
    int port = 4701; 

    StringBuffer instr = new StringBuffer(); 

    try { 
     InetAddress address = InetAddress.getByName(host); 

     Socket connection = new Socket(address, port); 

     BufferedOutputStream bos = new BufferedOutputStream(connection. 
       getOutputStream()); 

      OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII"); 

      String process = "marco" + (char) 13; 

      osw.write(process); 
      osw.flush(); 

      BufferedInputStream bis = new BufferedInputStream(connection. 
       getInputStream()); 

      InputStreamReader isr = new InputStreamReader(bis, "US-ASCII"); 

      int c; 
      while ((c = isr.read()) != 13) 
       instr.append((char) c); 

      connection.close(); 
      } 
      catch (Exception e){} 

      if(instr.toString().equals("")){ 
       //error 
      } 


} 

したがって、たとえば、私はどのようにサーバーを決定するために、サーバに様々な文字列を送信します応答します。たとえば、コードに見られるように、サーバーに「marco」を送信すると、「polo」が返されます。私はまた、メッセージが終わったことをプログラムに知らせるための区切り文字として(char) 13を持っています。

誰かが転送の時間を短縮する方法についていくつか考えていますか?私は、ナグルのアルゴリズムを無効にするなどのことを読んだ。助けてくれますか?おそらくソケットは私が純粋なスピードを望むならば行く方法ではありません。たぶん異なる言語やライブラリが速くなるでしょうか?

+0

あなたは「少し遅い」と思いますか? – Mat

+0

できるだけ早くそれを必要とするケースが増えています:) –

+3

はい、それは私の主張です。それはどういうことなのですか? – Mat

答えて

4

へのマルチスレッド対応を示した素晴らしい記事では、あなたの接続をクローズする必要があります。さもなければ、彼らは将来何らかのガベージコレクション時間まで開いたままです。

待ち時間が短くて済む場合は、DatagramSocket(TCPではなくUDP)を使用してください。あなたはメッセージ配信の保証を失い、失われたパケットを期待する必要がありますが、良いネットワーク上の短いメッセージでは、移植性のあるコードと同じくらい良い遅延があります。

もう1つの方法は、毎回クライアントのソケット接続を再オープンするのではなく、再利用することです。あなたのような小さなメッセージの場合、TCPのセットアップとティアダウンで大部分の時間が消費されている可能性があります。

マイクロ最適化は、文字単位の処理を停止し、 "marco"と "polo"をバイト文字列として一致させることです。しかし、目立った改善が起こる可能性は低いです。

+0

すばらしい提案ありがとうございます。接続を開いたままにしておくと言えば、これはどういう意味ですか?私は接続が開いたり閉じたりしたときに実際に何が起こっているのか少し混乱していると思う。開いている接続で一定のデータストリームが送信されていますか?私の "marco"メッセージが送られる前にサーバーとクライアントの間に通信がありますか?すなわち、互いに最初にお互いに言っているのですか? –

+1

あなたの例では、クライアントはソケットを開き、メッセージを送信し、応答を待ち、接続を閉じます。より現実的なシナリオでは、送受信ロジックの周りにwhileループが存在する可能性があります。その場合、すべてのループ反復でopen/closeの代わりに同じTCP接続を再利用したいと思うでしょう。追加の接続を行う予定があるかどうかわからない、より複雑なシナリオでは、アイドル状態の接続に有効期限のあるプールを使用できます。その場合、http://commons.apache.org/pool/ –

1

あなたはそれをより速くするために多種多様なことがありますが、変更する必要があることは明確です。通常、最長の遅延はネットワーク内にあります。

ループバックまたは低レイテンシのネットワークに接続していた場合、NIOを使用すると、はるかに高速になる可能性があります。しかし、通常のネットワークを使用している場合、インターネット接続を使用している場合は、プログラムの効率はあまり変わりません。

パフォーマンスを見るときは、エンドツーエンドのソリューション全体を見て、遅延がどこにあるのかを見極め、ソリューションを遅くする最大のものに集中する必要があります。

0

ソケットは非常に低レベルなので、使いやすいJavaライブラリがはるかに高速であるとは思っていません。 Javaは最も速い言語ではないかもしれませんし、そこで最も一般的なサーバーは通常C/C++で書かれています。しかし、多くの大規模なプロジェクトがJavaサーバー上で実行されています(TomcatResinJBoss)。

最適化に関しては、通常の方法はサーバーをマルチスレッド化することです。 ServerSocket.accept()の後に、リクエストの処理用に新しいスレッドを作成するので、サーバは他のクライアントにサービスを提供することができます。ここで

は、ソケット要求サーバー側で

http://www.oracle.com/technetwork/java/socket-140484.html

+0

答えをありがとう。実際には私がサービスする必要があるクライアントの数は1に過ぎませんが、それは興味深いものです –

関連する問題