我有一个应用程序必须通过 TCP 套接字将数据发送到另一个应用程序。这是从客户端到服务器的单向流。发送数据时,客户端必须重试/重新连接,并尝试确保在接收器/侦听器/服务器死亡/消失或断开连接时发送所有数据。我的代码如下:
public class TCPSocket implements Closeable {
private static final int SIXTY_FOUR_KB = 65536;
private final String ip;
private final int port;
private Socket socket;
private BufferedOutputStream writer;
public TCPSocket(String ip, int port) {
this.ip = ip;
this.port = port;
}
public TCPSocket connect() throws ConnectException {
try {
socket = new Socket(ip, port);
socket.setSendBufferSize(SIXTY_FOUR_KB);
writer = new BufferedOutputStream(socket.getOutputStream(), SIXTY_FOUR_KB);
} catch (Exception e) {
throw new ConnectException(e.getMessage());
}
return this;
}
public void write(String message) throws InterruptedException {
boolean succeeded = true;
do {
try {
writer.write(message.getBytes(StandardCharsets.UTF_8));
writer.write("\n".getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
System.out.println(e.getMessage());
succeeded = false;
// Exponential backoff to go here
try {
System.out.println("Attempting reconnection");
tryClose();
connect();
} catch (ConnectException connectException) {
System.out.println(connectException.getMessage());
}
}
} while (!succeeded);
}
private void tryClose() {
try {
close();
} catch (Exception ex) {
System.out.println("Failed closing TCPSocket");
}
}
@Override
public void close() throws IOException {
if (writer != null) {
writer.flush();
writer.close();
writer = null;
}
if (socket != null && !socket.isClosed()) {
socket.close();
socket = null;
}
}
}
注意:使用 BufferedOutputStream 的原因是因为我正在发送小消息,而所有其他方法在现实世界的测试场景中无法获得相同的吞吐量。
这一切对我来说都按预期工作,但是我有几点。
这是正确的方法还是完全疯狂并会导致严重的问题?
在打开新连接之前尝试清理和关闭连接和编写器时,会引发以下错误,我无法关闭 bufferedOutputStream
java.net.SocketException:对等方重置连接:套接字写入错误
如果我
socket.shutdownOutput();
在尝试关闭输出流之前,那也会引发异常。清理和重新连接的正确方法是什么?