2016-09-25 3 views
0

Ich versuche, mit einer C++ - Anwendung als Server aus einer Java-Webanwendung über Socket zu sprechen. Der Server macht eine binäre API im Protokollpuffer verfügbar (unter Verwendung von 2.6.1 auf beiden Seiten und Java 8). Auf Client versuchte ich einen Socket-Verbindungspool, um die Leistung zu beschleunigen. Der erste Aufruf war immer erfolgreich, und nachfolgende Aufrufe wurden zeitgesteuert ausgeführt, was Apache Commons Pool zwang, die Socket-Verbindung zu zerstören. Also habe ich einen einfachen Java-Server und Java-Client geschrieben, um zu debuggen, was los ist. Die Quellen sind unten:Mehrere Nachrichten streamen über einen Socket

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

} 

Hier Request und Response sind Protocol Buffer generierte Klassen. Der Client sendet eine Anfrage und erhält eine Antwort. Er sendet erneut eine weitere Anfrage, die den Socket wiederverwendet. Der Server empfängt diese zweite Anforderung nie und der Client erhält nie eine Antwort. Wie kann ich mehrere Nachrichten über denselben Socket streamen?

Beispielausgabe unter

Client-Ausgabe

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" 

Server Output

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" 

Danke,
AK

+0

Irgendeine Idee, was hier geschieht. Sobald ein Socket verwendet wurde, bleibt er bei nachfolgenden Anfragen hängen. – user2459396

Antwort

0

Ich habe das Problem gefunden und es gelöst. Es ist ein Problem in der ServerConnection1-Klasse. Die run-Methode dieses Threads kann nur eine Anfrage/Antwort verarbeiten. Durch das Einfügen einer while-Schleife in die run-Methode können beliebig viele Anfragen/Antworten bearbeitet werden.

Verwandte Themen