2016-09-25 13 views
0

Socketを介してJava WebアプリケーションからサーバーとしてC++アプリケーションと通信しようとしています。サーバーは、プロトコル・バッファー(両側で2.6.1とJava 8を使用)でバイナリーAPIを公開します。クライアントでは、パフォーマンスを向上させるためにソケット接続プールを試しました。最初の呼び出しは常に成功し、その後の呼び出しはタイムアウトしていたため、Apache Commons Poolはソケット接続を破棄していました。だから私は、何が起こっているのかをデバッグするために、単純なJavaサーバーとJavaクライアントを書きました。情報源は以下の通りです。ソケットを介した複数のメッセージストリーミング

syntax = "proto2"; 

option java_package = "com.es.protos"; 
option java_outer_classname = "RequestProtos"; 
option optimize_for = SPEED; 

message Request { 
    oneof request { 
     string ping = 3; 
     string field1 = 4; 
     string field2 = 5; 
     string field3 = 6 
    } 
} 

syntax = "proto2"; 

option java_package = "com.es.protos"; 
option java_outer_classname = "ResponseProtos"; 
option optimize_for = SPEED; 

message Response { 
    required string status = 1; 
    oneof response { 
     string ping = 3; 
     string field1 = 4; 
     string field2 = 5; 
     string field3 = 6 
    } 
} 

package com.es.socket; 

import com.es.protos.RequestProtos.Request; 
import com.es.protos.ResponseProtos.Response; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import java.io.*; 
import java.net.ServerSocket; 
import java.net.Socket; 

public class TcpServer1 { 

    final static Logger LOGGER = LoggerFactory.getLogger(TcpServer1.class.getName()); 

    public static void main(String[] args) throws Exception { 
     ServerSocket serverSocket = new ServerSocket(Integer.parseInt(args[0])); 
     Socket socket = null; 
     while (true) { 
      try { 
       socket = serverSocket.accept(); 
      } catch (IOException e) { 
       LOGGER.warn("Could not listen on port"); 
       System.exit(-1); 
      } 

      Thread thread = new Thread(new ServerConnection1(socket)); 
      thread.start(); 
     } 
    } 
} 

class ServerConnection1 implements Runnable { 

    static final Logger LOGGER = LoggerFactory.getLogger(ServerConnection.class.getName()); 

    private Socket socket = null; 

    ServerConnection1(Socket socket) { 
     this.socket = socket; 
    } 

    public void run() { 
     try { 
      serveRequest(socket.getInputStream(), socket.getOutputStream()); 
      //socket.close(); 
     } catch (IOException ex) { 
      LOGGER.warn("Error", ex); 
     } 
    } 

    public void serveRequest(InputStream inputStream, OutputStream outputStream) { 
     try { 
      read(inputStream); 
      write(outputStream); 
     } catch (IOException ex) { 
      LOGGER.warn("ERROR", ex); 
     } 
    } 

    private void write(OutputStream outputStream) throws IOException { 
     Response.Builder builder = Response.newBuilder(); 
     Response response = builder.setStatus("SUCCESS").setPing("PING").build(); 
     response.writeDelimitedTo(outputStream); 
     LOGGER.info("Server sent {}", response.toString()); 
    } 

    private void read(InputStream inputStream) throws IOException { 
     Request request = Request.parseDelimitedFrom(inputStream); 
     LOGGER.info("Server received {}", request.toString()); 
    } 

} 

package com.es.socket; 

import com.es.protos.RequestProtos.Request; 
import com.es.protos.ResponseProtos.Response; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

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

public class TcpClient1 { 

    final static Logger LOGGER = LoggerFactory.getLogger(TcpClient1.class.getName()); 

    private Socket openConnection(final String hostName, final int port) { 
     Socket clientSocket = null; 
     try { 
      clientSocket = new Socket(hostName, port); 
     } catch (IOException e) { 
      LOGGER.warn("Exception occured while connecting to server", e); 
     } 
     return clientSocket; 
    } 

    private void closeConnection(Socket clientSocket) { 
     try { 
      LOGGER.info("Closing the connection"); 
      clientSocket.close(); 
     } catch (IOException e) { 
      LOGGER.warn("Exception occured while closing the connection", e); 
     } 
    } 

    private void write(OutputStream outputStream) throws IOException { 
     Request.Builder builder = Request.newBuilder(); 
     Request request = builder.setPing("PING").build(); 
     request.writeDelimitedTo(outputStream); 
     LOGGER.info("Client sent {}", request.toString()); 
    } 

    private void read(InputStream inputStream) throws IOException { 
     Response response = Response.parseDelimitedFrom(inputStream); 
     LOGGER.info("Client received {}", response.toString()); 
    } 

    public static void main(String args[]) throws Exception { 
     TcpClient1 client = new TcpClient1(); 
     try { 
      LOGGER.info("Start - One socket for all calls"); 
      Socket clientSocket = client.openConnection("localhost", Integer.parseInt(args[0])); 
      OutputStream outputStream = clientSocket.getOutputStream(); 
      InputStream inputStream = clientSocket.getInputStream(); 
      for (int i = 0; i < 2; i++) { 
       LOGGER.info("REQUEST {}", i); 
       client.write(outputStream); 
       client.read(inputStream); 
      } 
      client.closeConnection(clientSocket); 
      LOGGER.info("End - One socket for all calls"); 
     } catch (Exception e) { 
      LOGGER.warn("Exception occured", e); 
      System.exit(1); 
     } 
    } 

} 

ここで、要求と応答はプロトコルバッファ生成クラスです。クライアントは1つの要求を送信し、応答を受信します。ソケットを再利用する別の要求を再度送信します。サーバーはこの2番目の要求を受信せず、クライアントは応答を受け取ることはありません。どのように私は同じソケット上で複数のメッセージをストリーミングすることができます。以下

サンプル出力

クライアントの出力

18:09:10.733 [main] INFO c.d.e.socket.TcpClient1 - Start --> One socket for all calls 
18:09:10.733 [main] INFO c.d.e.socket.TcpClient1 - REQUEST 0 
18:09:10.734 [main] INFO c.d.e.socket.TcpClient1 - Client sent ping: "PING" 
18:09:10.734 [main] INFO c.d.e.socket.TcpClient1 - Client received status: "SUCCESS" 
ping: "PING" 
18:09:10.734 [main] INFO c.d.e.socket.TcpClient1 - REQUEST 1 
18:09:10.735 [main] INFO c.d.e.socket.TcpClient1 - Client sent ping: "PING" 

サーバー出力

18:09:10.734 [Thread-0] INFO c.d.e.socket.ServerConnection - Server received ping: "PING" 
18:09:10.734 [Thread-0] INFO c.d.e.socket.ServerConnection - Server sent status: "SUCCESS" 
ping: "PING" 

おかげで、
AK

+0

ここで何が起こっているかわかりません。一度ソケットが使用されると、それ以降のリクエストでスタックされてしまいます。 – user2459396

答えて

0

問題が見つかり、解決しました。 ServerConnection1クラスの問題です。このスレッドのrunメソッドは、ただ1つの要求/応答を処理するように設計されています。 runメソッドにwhileループを置くことで、必要なだけ多くのリクエスト/レスポンスを処理できます。

関連する問題