[英]How to keep TCP sockets open?
我們的應用程序具有與許多服務器的類似乒乓的對話(每個服務器都有一個用於建立這些連接的對應線程)。 下面的代碼可以工作,但是它為每個新請求打開一個新連接,並且只能使用一次,這很快就會達到服務器設置的最大連接上限。
DataProvider.java
public static ZnResult sendTcpQuery(String xml, String url, int port) {
List<ZnXmlResult> results = new ArrayList<>();
String xmlString = xml != null ? new String((xml + "\n").getBytes()) : "";
int error = ZnResult.OK;
try (Socket clientSocket = new Socket(url, port)) {
clientSocket.setSoTimeout(CONNECTION_TIMEOUT);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
try (BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"))) {
outToServer.writeBytes(xmlString);
try (StringWriter responseFromServer = new StringWriter()) {
String readLine;
while ((readLine = inFromServer.readLine()) != null) {
...
}
}
outToServer.close();
clientSocket.close();
}
} catch (Exception ex) {
LOG.error("Exception {}", url + ":" + port, ex);
error = ZnResult.ERR;
}
return error == ZnResult.OK ? new ZnResult(results) : new ZnResult(error);
}
如何轉換它,以便所有事情都可以在一個連接中完成? 我想我會做這樣的事情:
SocketFactory.java
public class SocketFactory {
private static HashMap<String, Socket> socketsByAddress = new HashMap<>();
private static HashMap<Socket, DataOutputStream> outputStreamsBySocket = new HashMap<>();
private static HashMap<Socket, BufferedReader> readersBySocket = new HashMap<>();
public static Socket getSocket(String address) {
String ip = Tools.getIpFromAddress(address);
int port = Tools.getPortFromAddress(address);
Socket socket = socketsByAddress.get(address);
if (socket == null) {
try {
socket = new Socket(ip, port);
socket.setSoTimeout(60000);
socketsByAddress.put(address, socket);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return socket;
}
public static DataOutputStream getOutputStream(Socket socket) {
DataOutputStream outputStream = outputStreamsBySocket.get(socket);
if (outputStream == null) {
try {
outputStream = new DataOutputStream(socket.getOutputStream());
outputStreamsBySocket.put(socket, outputStream);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return outputStream;
}
public static BufferedReader getReader(Socket socket) {
BufferedReader reader = readersBySocket.get(socket);
if (reader == null) {
try {
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
readersBySocket.put(socket, reader);
} catch (IOException ex) {
Logger.getLogger(SocketFactory.class.getName()).log(Level.SEVERE, null, ex);
}
}
return reader;
}
}
DataProvider.java
public static ZnResult sendTcpQuery(String xml, String url, int port) {
List<ZnXmlResult> results = new ArrayList<>();
int error = ZnResult.OK;
try {
String xmlString = xml != null ? new String((xml + "\n").getBytes()) : "";
Socket clientSocket = SocketFactory.getSocket(url + ":" + port);
DataOutputStream outToServer = SocketFactory.getOutputStream(clientSocket);
BufferedReader inFromServer = SocketFactory.getReader(clientSocket);
outToServer.writeBytes(xmlString);
try (StringWriter responseFromServer = new StringWriter()) {
String readLine;
while ((readLine = inFromServer.readLine()) != null) {
...
}
}
} catch (Exception ex) {
LOG.error("Exception {}", url + ":" + port, ex);
error = ZnResult.ERR;
}
return error == ZnResult.OK ? new ZnResult(results) : new ZnResult(error);
}
但是它只是行不通,只有第一個通過。
該循環讀取直到流結束。
while ((readLine = inFromServer.readLine()) != null) {
流僅結束一次。 即您不能結束流,但是稍后再使用它。
您需要做什么?
"[EOF]"
嘗試像第一個代碼中那樣使用URL而不是IP地址來初始化Socket對象,然后查看它是否對您有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.