我有一个TCP客户端,每秒向一个只打印字符串的TCP服务器发送一个14字节的字符串。
客户端是Android应用程序,Server是在笔记本电脑上运行的简单Java应用程序。通信是从客户端到路由器的wifi,然后是以太网到笔记本电脑。
客户端连接到服务器确定并开始发送消息,但在不确定的时间后服务器停止接收消息。
查看来自服务器的wireshark流量显示服务器已确认最后一条消息但客户端显然从未收到ACK,因为它重新发送消息并且服务器发送DUP ACK。之后,在我明确关闭客户端上的socket.outputStream()
之前,不会再显示任何消息,此时服务器会收到所有消息,Wireshark会显示包含所有缺失消息的TCP帧。
注意我在每条消息后都在冲洗。并且TCP_NODELAY没有效果。
注意,以下代码不适用于生产用途。这只是我可以调试它。
客户端:
private class SocketSender implements Runnable {
private final Socket socket = new Socket();
public void run() {
Log.d(TAG, "Starting SocketSender");
toggleButtons(SocketState.Transmitting);
try {
startSending();
} catch (IOException e) {
Log.d(TAG, "", e);
}
toggleButtons(SocketState.AwaitingClose);
Log.d(TAG, "Stopping SocketSender");
}
private void startSending() throws IOException {
int counter = 1;
Log.d(TAG, "Opening Socket to " + HOST_ADDRESS + ":" + HOST_PORT);
//socket.setTcpNoDelay(true);
//socket.setPerformancePreferences(0, 1, 0);
socket.connect(new InetSocketAddress(HOST_ADDRESS, HOST_PORT), 3000);
Log.d(TAG, "OpenedSocket");
try {
final OutputStream stream = socket.getOutputStream();
final PrintWriter output = new PrintWriter(stream);
while (sending) {
final String message = "Ping pingId=" + counter;
output.println(message);
output.flush();
Log.d(TAG, "Sent message : " + message);
counter++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Log.d(TAG, "Sleep interrupted", e);
}
}
output.close();
} finally {
//socket.close();
}
}
private void closeSocket() {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
Log.d(TAG, "Could not close Socket", e);
}
}
}
}
服务器:
private void readStream() throws IOException {
final ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
final Socket socket = serverSocket.accept();
final InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
final BufferedReader in = new BufferedReader(streamReader);
final SimpleDateFormat format = new SimpleDateFormat("YY-MM-DD HH:mm:ss.SSS");
long lastMessage = System.currentTimeMillis();
while (true) {
final String inputLine = in.readLine();
long thisMessage = System.currentTimeMillis();
if (inputLine == null) {
System.out.println(" No more input from : " + socket);
break;
}
System.out.println(format.format(new Date(thisMessage)) + " '" + inputLine + "' from : " + socket + " millisSinceLastMsg=" + (thisMessage - lastMessage));
lastMessage = thisMessage;
}
socket.close();
}
答案 0 :(得分:0)
这里的关键是发送方没有收到ACK。这是一个网络问题,而不是编码问题。令人惊讶的是,发件人没有填写其发送缓冲区,阻止,最终超时待处理的发送,并重置连接。
您可能最好在接收器上设置读取超时,并在连接时关闭连接。通过这种方式,客户端将重置连接,并且至少会知道某些错误,然后它可以重新连接或任何适当的连接。
答案 1 :(得分:0)
在测试了8个不同的接入点和11种不同的手机型号之后,这似乎只是华为Y300与某些接入点结合时的问题。
我无法确定AP导致锁定的情况,所以我决定尽可能避免使用这款手机。