Ich debugge derzeit zwei Java-Anwendungen, die Daten über eine TCP-Verbindung austauschen.
Eine der Anwendungen, der TCP-Client, sendet periodisch dringende Daten an den anderen, den TCP-Server, indem er Socket#sendUrgentData(int) aufruft. Beim 18. Versuch, die dringenden Daten zu senden, wirft der TCP-Client die folgende Ausnahme
java.io.IOException: BrokenPipe
bei java.net.PlainSocketImpl.socketSendUrgentData(Native Method)
bei java.net.PlainSocketImpl.sendUrgentData(PlainSocketImpl.java:541)
bei java.net.Socket.sendUrgentData(Socket.java:927)
Der TCP-Server wirft diese Ausnahme
java.net.SocketException: Software caused connection abort: recv failed
bei java.net.SocketInputStream.socketRead0(Native Method)
bei java.net.SocketInputStream.read(Unknown Source)
bei java.net.SocketInputStream.read(Unknown Source)
Ich glaube, die Ausnahmen werden durch den Versuch verursacht, auf eine geschlossene Verbindung/ein geschlossenes Socket zu schreiben/lesen. Was ich nicht verstehe ist, warum die Verbindung oder das Socket nach dem Aufruf von sendUrgentData() 17 Mal geschlossen wird. Ich kann es wiederholen und es tritt immer nach 17 Mal auf.
Wenn ich den Client und den Server unter Windows ausführe, tritt das Problem auf. Wenn ich den Client und den Server unter Solaris ausführe, tritt das Problem nicht auf. Wenn ich den Client auf Solaris und den Server auf Windows ausführe, tritt das Problem auf. Wenn ich den Client auf Windows und den Server auf Solaris ausführe, tritt das Problem nicht auf. Das lässt mich denken, es könnte mit Windows zusammenhängen?
Bei Verwendung von Wireshark sehe ich den folgenden Datenverkehr auf der Verbindung
--> = vom TCP-Client zum TCP-Server
<-- = vom TCP-Server zum TCP-Client
--> [PSH, ACK, URG] (Seq=1, Ack=1)
<-- [ACK] (Seq=1, Ack=2)
--> [PSH, ACK, URG] (Seq=2, Ack=1)
<-- [ACK] (Seq=1, Ack=3)
...
--> [PSH, ACK, URG] (Seq=17, Ack=1)
<-- [RST, ACK] (Seq=1, Ack=18)
Ich habe einige einfache Testklassen geschrieben, die das Problem zeigen.
TCPServer.java IP_Address Port
public class TCPServer
{
public static void main(String[] args) throws Exception
{
ServerSocket socket = new ServerSocket();
socket.bind(new InetSocketAddress(args[0], Integer.parseInt(args[1])));
System.out.println("GEBUNDEN/" + socket);
Socket connection = socket.accept();
System.out.println("VERBUNDEN/" + connection);
int b;
while ((b = connection.getInputStream().read()) != -1) {
System.out.println("LESEN byte: " + b);
}
System.out.println("SCHLIEßEN ..");
connection.close();
socket.close();
}
}
TCPClient.java IP_Address Port Interval_Between_Urgent_Data
public class TCPClient
{
public static void main(String[] args) throws Exception
{
final Socket socket = new Socket();
socket.connect(new InetSocketAddress(InetAddress.getByName(args[0]), Integer.parseInt(args[1])));
System.out.println("VERBUNDEN/"+socket);
Timer urgentDataTimer = new Timer(true);
urgentDataTimer.scheduleAtFixedRate(new TimerTask()
{
int n = 0;
public void run() {
try {
System.out.println("SENDE DRINGENDE DATEN ("+(++n)+") ..");
socket.sendUrgentData(1);
System.out.println("GESCHICKT DRINGENDE DATEN");
} catch (Exception e) {
e.printStackTrace();
}
}
}, 1000, Integer.parseInt(args[2]));
int b;
while ((b = socket.getInputStream().read()) != 1) {
System.out.println("LESEN byte: " + b);
}
System.out.println("SCHLIEßEN ..");
urgentDataTimer.cancel();
socket.close();
}
}
Kann mir jemand erklären, was hier passiert?
Danke.