2016-09-25 2 views
0

Socket을 통해 Java 웹 응용 프로그램의 서버로 C++ 응용 프로그램과 통신하려고합니다. 서버는 프로토콜 버퍼 (양쪽 2.6.1 및 Java 8 사용)에 2 진 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); 
     } 
    } 

} 

여기 요청 및 응답은 프로토콜 버퍼 생성 클래스입니다. 클라이언트는 하나의 요청을 보내고 응답을받습니다. 소켓을 재사용하는 또 다른 요청을 다시 보냅니다. 서버는이 두 번째 요청을 수신하지 않으며 클라이언트는 응답을 수신하지 않습니다. 동일한 소켓을 통해 여러 개의 메시지를 스트리밍 할 수있는 방법은 무엇입니까? 아래

샘플 출력

클라이언트 출력

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 메소드에서 while 루프를 사용하면 원하는만큼 많은 요청/응답을 처리 할 수 ​​있습니다.