[英]TCP server and TCP client in java
我試圖在我的春季啟動應用程序中實現TCP服務器和客戶端。 最初我的控制器從另一個應用程序接收響應,在收到此響應時,我的服務類調用另一個設置tcp連接的方法。 建立tcp連接后,我調用一個設置tcp客戶端的方法。 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;
}
}
我不想變得粗魯,但你的所有回答都基於'關鍵詞'。 應用程序本身阻止了您嘗試使用的網絡端口。 使用調用可在服務器端訪問的實際函數的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;
}
以下是如何使用它:
這是示例代碼:
// 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
*/
代碼應該工作,我使用Notepad ++編寫它,這就是為什么例外>有點通用,因為我不記得我應該在沒有IDE的情況下使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.