2017-05-30 16 views
1

私は春のブートアプリケーションでTCPサーバーとクライアントを実装しようとしています。 最初に私のコントローラは別のアプリケーションから応答を受け取ります。この応答を受信すると、私のサービスクラスはtcp接続を設定する別のメソッドを呼び出します。 tcp接続が確立された後、私はtcpクライアントを設定するメソッドを呼び出します。 TCPサーバーは、接続が確立されたマシンからのメッセージの受信を継続し、メッセージ名に基づいてさまざまなアクションが実行されます。私はコードを実行するたびに、私は次のエラーを取得する:TCPサーバーとJavaクライアントのTCPクライアント

java.net.BindException: Address already in use: JVM_Bind 
    at java.net.DualStackPlainSocketImpl.bind0(Native Method) 
    at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106) 
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:387) 
    at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190) 
    at java.net.ServerSocket.bind(ServerSocket.java:375) 
    at java.net.ServerSocket.<init>(ServerSocket.java:237) 
    at java.net.ServerSocket.<init>(ServerSocket.java:128) 
    at com.epbRestServer.tcp.TCPServer.setupTCPConnection(TCPServer.java:24) 
    at com.epbRestServer.service.impl.EPBRestServerServiceImpl.handleStartEPC(EPBRestServerServiceImpl.java:28) 
    at com.epbRestServer.controller.EPBRestServerController.startEPC(EPBRestServerController.java:27) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) 
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

TCPクライアントとTCPサーバーメソッドを呼び出すコード:

public ResponseBean handleStartEPC(RequestBean request) { 
    // Code for establishing tcp connection 
    ResponseBean response = new ResponseBean(); 

    if (request != null) { 
     TCPServer tcpServer = new TCPServer(); 
     response = tcpServer.setupTCPConnection(request); 
     if (response.getTcpConnect()) { 
      TCPClient tcpClient = new TCPClient(); 
      TCPRequestBean tcpBean = new TCPRequestBean(); 
      String str = new String(); 
      str = str.concat("IP:").concat(request.getIpAddress()).concat(",NodeName:").concat(request.getVduName()) 
        .concat(",Interface:").concat(request.getInterfaceName()); 
      int length = str.length(); 
      str = "Length:" + length +"," + str; 
      tcpBean.setIpAddress(request.getIpAddress()); 
      tcpBean.setInputData(str); 
      response = tcpClient.setupTCPClient(tcpBean); 
     } 

     else { 
      response.setStatus("FAILURE"); 
     } 

    } 

    else { 
     response.setStatus("FAILURE"); 
    } 

    return response; 
} 

TCPクライアントとTCPサーバー用のコード

public class TCPServer { 

    @Autowired 
    EPBRestServerService epbRestServerService; 

    public ResponseBean setupTCPConnection(RequestBean request) { 

     ResponseBean response = new ResponseBean(); 
     try { 
      ServerSocket server = new ServerSocket(8000); 
      Socket s = server.accept();// establishes connection 
      DataInputStream dis = new DataInputStream(s.getInputStream()); 
      String str = (String) dis.readUTF(); 
      VNFNotificationRequestBean vnfRequestBean = new VNFNotificationRequestBean(); 
      System.out.println("message:" + str); 
      switch (str.toLowerCase()) { 
      case "restAPIResponse": 
       response.setTcpConnect(true); 
       response.setStatus("SUCCESS"); 
       break; 
      case "startsuccess": 
       vnfRequestBean.setEvent("StartSuccess"); 
       vnfRequestBean.setSystemId(request.getSystemId()); 
       vnfRequestBean.setContent("ContentType - application/json"); 
       response = epbRestServerService.triggerEvent(request, vnfRequestBean); 
       break; 
      case "initsuccess": 
       vnfRequestBean.setEvent("InitSuccess"); 
       vnfRequestBean.setSystemId(request.getSystemId()); 
       vnfRequestBean.setContent("ContentType - application/json"); 
       response = epbRestServerService.triggerEvent(request, vnfRequestBean); 
       break; 
      case "configuresuccess": 
       vnfRequestBean.setEvent("ConfigureSuccess"); 
       vnfRequestBean.setSystemId(request.getSystemId()); 
       vnfRequestBean.setContent("ContentType - application/json"); 
       response = epbRestServerService.triggerEvent(request, vnfRequestBean); 
       break; 
      default: 
       response.setStatus("FAILURE"); 
       break; 
      } 
      server.close(); 
     } catch (IOException e) { 
      response.setTcpConnect(false); 
      e.printStackTrace(); 
     } 
     return response; 

    } 

    public class TCPClient { 

     public ResponseBean setupTCPClient(TCPRequestBean request) { 

      ResponseBean response = new ResponseBean(); 
      try { 
       Socket s = new Socket(request.getIpAddress(), 8000); 
       DataOutputStream dout = new DataOutputStream(s.getOutputStream()); 
       dout.writeUTF(request.getInputData()); 
       dout.flush(); 
       dout.close(); 
       s.close(); 
       response.setStatus("SUCCESS"); 
      } catch (IOException e) { 
       System.out.println(e); 
       response.setStatus("FAILURE"); 
      } 
      return response; 
     } 

    } 
+0

何かがすでにポート8000​​を使用している - それを把握するには、netstatなどのツールを使用しています。それはあなた自身のコードかもしれませんか? –

+0

@ SkaryWombatええ、それは私のコードがこのポートを使用しているようです。ここの問題は私のコードがこのマシンとの接続を確立できません。 –

+0

'StartEPC'イベントごとに1回ではなく、アプリケーション実行ごとに' ServerSocket'を1回設定する必要があります。しかし、あなた自身のインプロセスサーバーのクライアントであるように見えるので、TCPを使用するという点を全く理解することは困難です。 – EJP

答えて

0

私は無礼になりたくはありませんが、あなたはすべての回答を「キーワード」に基づいています。アプリケーション自体が、利用しようとしているネットワークポートをブロックしています。サーバ側でアクセス可能なacutal関数を呼び出すTCPClientを使う方がはるかに簡単です。引数を渡して戻り値を取得することさえできます。はるかに柔軟で信頼性の高いものです。

ここTCPServerのコードです:

public class TCPServer { 
/** 
* Class Constants 
*/ 
public static int TCP_CLIENTS_INFINITE = 0; 

/** 
* Class Variables 
*/ 
private int serverPort; // Port on which the server will listen for incoming connections 
private String serverIP; // IP that the server will be listening on 
private int maxClients; // If set to 0 the max client amount is infinite 
private int threadCount; // Displays the current amount of running TCP threads, can be interpreted as amount of connected clients 
private Class classInstance; // Instance of a class that contains the functions needed for the server to operate 
private boolean serverWorking = false; // Indicates if the server is online 

/** 
* Class Functions 
*/ 
private ServerSocket serverSocket; 

/** 
* TCPServer class constructor 
* 
* @param serverPort   Port on which the server will listen to for incoming connections 
* @param maxClients   Maximum number of connected clients 
* @param serverFunctionsClass Class which contains all the server functions 
*/ 
public TCPServer(int serverPort, int maxClients, Class serverFunctionsClass) { 
    try { 

     this.serverPort = serverPort; 
     System.out.println("Server port has been set to: " + serverPort); 
     this.maxClients = maxClients; 
     System.out.println("Max connected clients has been set to: " + maxClients); 
     this.classInstance = serverFunctionsClass; 
     System.out.println("Server functions class has been set"); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Bind the TCP Server Socket to a specific ip address 
* 
* @param ip String representation of an IP Address 
*/ 
public void bindSocketToIP(String ip) { 
    try { 
     this.serverIP = ip; 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Start the server and begin listening for connections 
*/ 
public void start() { 
    try { 
     if (!serverWorking) { 

      if (serverIP != null) { 
       serverSocket = new ServerSocket(serverPort, 50, InetAddress.getByName(serverIP)); 
      } else { 
       serverSocket = new ServerSocket(serverPort); 
      } 
      System.out.println("TCP Server is now listening for new connections, on port: " + serverSocket); 

      serverWorking = true; 

      if (maxClients == 0) { 
       maxClients = 999; 
      } 

      while (true) { 
       // Open Client socket to handle client connections 
       Socket clientSocket = serverSocket.accept(); 

       if (clientSocket != null && getThreadCount() < getMaxClients()) { 
        new Thread(() -> new TCPClientHandler(clientSocket)).start(); 
       } else { 
        System.out.println(String.format("Exceeded maximum connected clients limit: %d/%d", getThreadCount(), getMaxClients())); 
       } 
      } 
     } else { 
      return; 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Stop the server 
*/ 
public void stop() { 
    try { 
     serverSocket.close(); 
     serverWorking = false; 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* @return Current amount of connected clients a.k.a running threads 
*/ 
public synchronized int getThreadCount() { 
    return threadCount; 
} 

/** 
* @return Defined number of maximum clients accepted by the server at any given time 
*/ 
public synchronized int getMaxClients() { 
    return maxClients; 
} 


/** 
* Class which processes the client requests 
*/ 
class TCPClientHandler { 

    /** 
    * Handle Client in a separate thread 
    * 
    * @param clientSocket TCP ServerSocket instance 
    */ 
    public TCPClientHandler(Socket clientSocket) { 

     // Inner Variables 
     String clientSentence = null, clientIP = null; 
     ObjectOutputStream toClient = null; 
     ObjectInputStream fromClient = null; 
     Object[] argumentsObjectArray; 
     ArrayList argumentsCollectionArray; 

     try { 
      if (clientSocket.isConnected() && !clientSocket.isClosed()) { 

       // Incline the threadNumber 
       threadCount++; 

       // Get connection input stream 
       fromClient = new ObjectInputStream(clientSocket.getInputStream()); 

       // Get connection output stream 
       toClient = new ObjectOutputStream(clientSocket.getOutputStream()); 

       while (true) { 
        try { 
         // Process fromClient 
         argumentsObjectArray = (Object[]) fromClient.readObject(); 

         // Read client sentence 
         clientSentence = (String) argumentsObjectArray[0]; 

         // Remove the client Sentence from argument array 
         argumentsCollectionArray = new ArrayList(Arrays.asList(argumentsObjectArray)); 
         Collection c = argumentsCollectionArray; 
         c.remove(clientSentence); 
         argumentsObjectArray = c.toArray(); 

         // Print was was received by the server 
         System.out.println("Function to be invoked: '" + clientSentence + "'"); 

         for (Object o : argumentsObjectArray) { 
          System.out.println("Parameter: '" + o + "' Type: '" + o.getClass().getTypeName() + "'"); 
         } 

         // Get Client IP Address 
         clientIP = clientSocket.getInetAddress().toString(); 

         // Write data to client 
         toClient.writeObject(processServerFunction(clientSentence, argumentsObjectArray)); 
        } catch (Exception ex) { 
         System.out.println("Connection with client: " + clientIP + ", has been terminated, closing sockets..." + '\n'); 
         if (clientSocket != null) { 
          try { 
           clientSocket.close(); 
          } catch (Exception e) { 
           // DO NOTHING 
          } 
         } 
         if (fromClient != null) { 
          try { 
           fromClient.close(); 
          } catch (Exception e) { 
           // DO NOTHING 
          } 
         } 
         if (toClient != null) { 
          try { 
           toClient.close(); 
          } catch (Exception e) { 
           // DO NOTHING 
          } 
         } 
         threadCount--; 
         break; 
        } 

       } 
      } 
     } catch (Exception ex) { 
      try { 
       System.out.println("Connection with client: " + clientIP + ", has been terminated, closing sockets..." + '\n'); 
       if (clientSocket != null) { 
        try { 
         clientSocket.close(); 
        } catch (Exception e) { 
         // DO NOTHING 
        } 
       } 
       if (fromClient != null) { 
        try { 
         fromClient.close(); 
        } catch (Exception e) { 
         // DO NOTHING 
        } 
       } 
       if (toClient != null) { 
        try { 
         toClient.close(); 
        } catch (Exception e) { 
         // DO NOTHING 
        } 
       } 
       threadCount--; 
       ex.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    /** 
    * Process Server Function, by it's String name 
    * 
    * @param functionName Name of the function or method interpreted as a String 
    * @param args   Array of objects that which represent both function name and it's arguments if any 
    * @return String value received from a invoked function 
    */ 
    public Object processServerFunction(String functionName, Object[] args) { 
     try { 

      Method functionInvoker; 
      Object clientEcho; 

      if (args.length >= 1) { 
       functionInvoker = classInstance.getDeclaredMethod(functionName, getParameterTypes(classInstance, functionName)); 
       clientEcho = functionInvoker.invoke(classInstance, args); 
      } else { 
       functionInvoker = classInstance.getDeclaredMethod(functionName); 
       clientEcho = functionInvoker.invoke(classInstance); 
      } 

      if (clientEcho != null) { 
       System.out.println("Sending to client: " + clientEcho); 
      } 
      return clientEcho; 
     } catch (Exception ex) { 
      ex.printStackTrace(); 
      System.out.println("Client requested function does not exists on the server"); 
      return "Client requested function does not exists on the server"; 
     } 
    } 

    /** 
    * Get all the function parameter types dynamically 
    * 
    * @param aClass  class in which the function is located 
    * @param methodName function name 
    * @return Class[] of parameter types 
    */ 
    private Class<?>[] getParameterTypes(Class<? extends Object> aClass, String methodName) { 
     try { 
      for (Method m : aClass.getDeclaredMethods()) { 
       if (m.getName().equals(methodName)) { 
        return m.getParameterTypes(); 
       } 
      } 

      // If nothing have been found return null value 
      return null; 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
      return null; 
     } 
    } 
} 

ここれるtcpClientコードだ:

public class TCPClient { 
/** 
* Variables 
*/ 
private String serverIP; 
private int serverPort; 
private Socket clientSocket; 
private boolean connected = false; 
private ObjectOutputStream outToServer; 
private ObjectInputStream inFromServer; 

/** 
* Class constructor 
* 
* @param serverIP String value that's representing the server ip 
* @param serverPort Integer value that represents server port 
*/ 
public TCPClient(String serverIP, int serverPort) { 
    try { 
     this.serverIP = serverIP; 
     this.serverPort = serverPort; 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Establish connection with the specified TCP server 
*/ 
public void connect() { 
    try { 
     if (!connected) { 
      try { 
       System.out.println(String.format("Trying to connect to: %s on port: %d", getServerIP(), getServerPort())); 
       clientSocket = new Socket(getServerIP(), getServerPort()); 
       System.out.println("Connected !"); 
       connected = true; 
       // Create ObjectStreams 
       outToServer = new ObjectOutputStream(clientSocket.getOutputStream()); 
       inFromServer = new ObjectInputStream(clientSocket.getInputStream()); 
      } catch (Exception e) { 
       connected = false; 
       if (clientSocket != null) { 
        clientSocket.close(); 
        System.out.println(String.format("Could not connect to: %s on port: %d", getServerIP(), getServerPort())); 
       } 
      } 
     } else { 
      return; 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Disconnect client for the currently connected server 
*/ 
public void disconnect() { 
    try { 
     if (connected) { 
      clientSocket.close(); 
      connected = false; 
     } 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
    } 
} 

/** 
* Invoke server side functions 
* 
* @param serverSideFunction Object representing both function name and its parameters 
* @return String vale of a server side function return value 
*/ 
public Object invokeFunction(Object[] serverSideFunction) { 
    try { 
     if (clientSocket != null && connected) { 
      outToServer.writeObject(serverSideFunction); 
      Object modifiedSentence = inFromServer.readObject(); 
      if (modifiedSentence != null) { 
       System.out.println("Received from server: " + modifiedSentence); 
      } 
      return modifiedSentence; 
     } 
     return null; 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     return null; 
    } 
} 

/** 
* Get server ip data 
* 
* @return String value of Server IP 
*/ 
public String getServerIP() { 
    return serverIP; 
} 

/** 
* Get server port data 
* 
* @return Integer value of Server Port 
*/ 
public int getServerPort() { 
    return serverPort; 
} 

は、ここでそれを使用する方法は次のとおりです。

  1. クリートは、
    1. TCPServerのインスタンスを作成し、必要なデータを提供してから、新しいスレッドでサーバーを起動します。
    2. 、れるtcpClientのインスタンスを作成し、すべてのデータを提供し、(.connectを呼び出す)
    3. 利用TCPClient.invokeFunction()

サーバー側の機能を呼び出すためにここにサンプルコードです:

// This is how you start the server, yes it's that simple, just don't start it //everytime you call a function. Start it once. 

TCPServer tcpServer = new TCPServer(6969, 0, MyFuntions.class); 

new Thread(() -> { 
    tcpServer.start(); 
}).start(); 


// Now create a TCPClient instance 
TCPClient tcpClient = new TCPClient("Server IP as String", 6969); 

tcpClient.connect(); // You can call it in a different Thread if you want 

/* 
Now lets say you have a server side function that's called: 'doMath(int x, int y)' 

what you want to do to call it, and pass parameters is quite simple: 
*/ 

tcpClient.invokeFunction(new Object[]{"doMath", 5, 10); 

/* 
The server will invoke this function do what you wanted with those number 
and if you want to return the outcome to the client it will do so aswell. 

Just remember that the server-side functions and methods have to be public 
and static 
*/ 

The code should work, I was writing it using Notepad++ so that's why exceptions >are a bit generic since I can't remeber which i should use without the IDE.

関連する問題