Name: nt126004 Date: 08/17/2001
C:\Mis documentos\pruebasockets>c:\jdk\jdk1.2.2\bin\java -version
java version "1.2.2"
Classic VM (build JDK-1.2.2-001, native threads, symcjit)
I have an application wich is intended to write data in string format via a
socket. There is a moment when i want that one of the peers close the
connection. This closing should cause that the other peer gets an exception
wich prevents it from continuing sending data to the socket.
When the peer wich did not close the socket tries to write on the closed
socket, it gets an exception, but only the second and later times it tries to.
Thus, the first message sent does not get an exception though there in nobody
to get the message.
I have get this problem both in windowsNT 4.0 and in Windows95 platforms, and
both in java 1.2.2 and java 1.3 jdk's
I have read the bug 4213824, which is similar to this, but there are two
differences in this report:
i do not have problems to obtain an exception when READING from the closed
socket.
I abide that the closed socket causes a exception when writing, but only the
second and later times.
Next i attach the code of a program which illustrates the problem:
This program shows two windows, one for controlling a server side and one for
controlling the client side.
1. Click on the "Accept" button on the window for the server
2. Click on the "Connect" button on the window for the client
At this point the client and the server should be connected
3. (Optional) Click on the receive button on the client. This will launch a
thread that will cause that all messages sent from the server appear on the
panel in the client
4. (Optional) Click on the "send" button on the server to send messages to the
client. The message will be the text of the text box included in the server.
Steps 3 and 4 are oprionals, but they are interesting to ensure that the
comunication is correct
5. Click on the "close" button on the client. This will close the socket
(and its associated writer)
6. Click on the "send" button on the server. Here is where the problem can be
seen. The program is triying to write on a closed socket and should get an
exception because of that, but it succeeds on the write operation instead!.
7. Click on the "send" button again. Now the program gets an exception when
writing to the socket.
Some preliminary explanations to the attached code:
1. The program has been developed with JBuilder3.0, (but i have compiledrun it
with JDK1.2.2 get from a Sun page), so the code to construct the windows and
its components is generated by JBuilder and is not intended to be clear. In
fact, i recommend not to read the jbInit methods not the class "Lanzador". The
only reason i include these sources is to allow the program to be run directly.
2. The program uses the ip direction "127.0.0.1" to connect the socket, wich is
supposed to be the direction of the local host. If the program is not going to
run on the same machine this direction should be changed accordingly.
3. The program uses a bufferedReader and a bufferedWriter to read and write
from an to the socket. These objects are closed prior to close the socket,
following the advice from bug 4213824. I have tried to write to the socket
using the PrintWriter class and have get the same result.
4. The program relies on the buffered writer and reader to close the
outputStream of the socket when they are closed, but i have tried to close the
Stream directly and get the same result.
5. The program forces the actual writing of the messages by calling the flush
method of the writer
And here cames the code:
/* This is a class generated by JBuilder to launch the program. It is necesary
to excecute the program but is is not necesary to understand the problem,
so you need not to read it */
import javax.swing.UIManager;
import java.awt.*;
public class Lanzador
{
boolean packFrame = false;
//Construct the application
public Lanzador()
{
TfrmPrincipal frame = new TfrmPrincipal();
TfrmSecundaria sec = new TfrmSecundaria();
//Validate frames that have preset sizes
//Pack frames that have useful preferred size info, e.g. from their layout
if (packFrame)
frame.pack();
else
frame.validate();
//Center the window
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Dimension frameSize = frame.getSize();
if (frameSize.height > screenSize.height)
frameSize.height = screenSize.height;
if (frameSize.width > screenSize.width)
frameSize.width = screenSize.width;
frame.setLocation((screenSize.width - frameSize.width) / 2,
(screenSize.height - frameSize.height) / 2);
frame.setVisible(true);
}
//Main method
public static void main(String[] args)
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch(Exception e)
{
}
new Lanzador();
}
}
/* Here comes the class for the server. You need not read the jbInit method */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class TfrmPrincipal extends JFrame implements Runnable
{
BorderLayout borderLayout1 = new BorderLayout();
Button cmdAccept = new Button();
Button cmdClose = new Button();
TextField edt = new TextField();
TextArea txa = new TextArea();
Button cmdSend = new Button();
ServerSocket ssk;
Socket sck;
OutputStreamWriter osw;
BufferedWriter bw;
//Construct the frame
public TfrmPrincipal()
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
jbInit();
ssk = new ServerSocket(5000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
//Component initialization
/* You need not to read this method to understand the problem */
private void jbInit() throws Exception
{
cmdAccept.setLabel("Accept");
cmdAccept.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdAccept_actionPerformed(e);
}
});
this.getContentPane().setLayout(borderLayout1);
this.setSize(new Dimension(400, 300));
this.setTitle("sockets trial");
cmdClose.setLabel("Close");
cmdClose.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdClose_actionPerformed(e);
}
});
edt.setText("Some text");
txa.setText("");
cmdSend.setLabel("send");
cmdSend.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdSend_actionPerformed(e);
}
});
this.getContentPane().add(cmdAccept, BorderLayout.WEST);
this.getContentPane().add(edt, BorderLayout.SOUTH);
this.getContentPane().add(txa, BorderLayout.CENTER);
this.getContentPane().add(cmdSend, BorderLayout.NORTH);
this.getContentPane().add(cmdClose, BorderLayout.EAST);
}
//Overridden so we can exit on System Close
protected void processWindowEvent(WindowEvent e)
{
super.processWindowEvent(e);
if(e.getID() == WindowEvent.WINDOW_CLOSING)
{
System.exit(0);
}
}
void cmdAccept_actionPerformed(ActionEvent e)
{
Thread hiloConexion = new Thread(this);
hiloConexion.start();
}
void cmdClose_actionPerformed(ActionEvent e)
{
try
{
sck.getOutputStream().close();
osw.close();
bw.close();
sck.setSoLinger(true, 0);
sck.close();
txa.append("closed\n");
}
catch(Exception ex)
{
txa.append(ex.getMessage() + "\n");
ex.printStackTrace();
}
}
void cmdSend_actionPerformed(ActionEvent e)
{
if (sck != null)
try
{
bw.write(edt.getText());
// bw.flush();
bw.newLine();
bw.flush();
txa.append("String '" + edt.getText() + "' sent\n");
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
public void run()
{
try
{
sck = ssk.accept();
txa.append("concected\n");
osw = new OutputStreamWriter(sck.getOutputStream());
bw = new BufferedWriter(osw);
}
catch(Exception ex)
{
txa.append(ex.getMessage() + "\n");
ex.printStackTrace();
}
}
}
/* And here comes the class for the client. You need not read the jbInit method
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
public class TfrmSecundaria extends JFrame implements Runnable
{
Panel panel1 = new Panel();
Button cmdConnect = new Button();
BorderLayout borderLayout1 = new BorderLayout();
Button cmdReceive = new Button();
JTextField edt = new JTextField();
InputStreamReader isr;
BufferedReader br;
Socket sck;
TextArea txa = new TextArea();
Button cmdClose = new Button();
public TfrmSecundaria()
{
try
{
jbInit();
setSize(400, 400);
setVisible(true);
}
catch(Exception e)
{
e.printStackTrace();
}
}
private void jbInit() throws Exception
{
cmdConnect.setLabel("Connect");
cmdConnect.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdConnect_actionPerformed(e);
}
});
panel1.setLayout(borderLayout1);
cmdReceive.setLabel("Receive");
cmdReceive.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdReceive_actionPerformed(e);
}
});
edt.setText("some thing");
txa.setText("");
cmdClose.setLabel("close");
cmdClose.addActionListener(new java.awt.event.ActionListener()
{
public void actionPerformed(ActionEvent e)
{
cmdClose_actionPerformed(e);
}
});
this.getContentPane().add(panel1, BorderLayout.CENTER);
panel1.add(cmdConnect, BorderLayout.WEST);
panel1.add(cmdReceive, BorderLayout.EAST);
panel1.add(edt, BorderLayout.NORTH);
panel1.add(cmdClose, BorderLayout.SOUTH);
panel1.add(txa, BorderLayout.CENTER);
}
void cmdConnect_actionPerformed(ActionEvent e)
{
try
{
sck = new Socket("127.0.0.1", 5000);
txa.append("coneected\n");
}
catch(Exception ex)
{
txa.append(ex.getMessage() + "\n");
ex.printStackTrace();
}
}
void cmdReceive_actionPerformed(ActionEvent e)
{
Thread hiloConexion = new Thread(this);
hiloConexion.start();
}
public void run()
{
String sCadena = "";
try
{
if (sck != null)
{
isr = new InputStreamReader( sck.getInputStream());
br = new BufferedReader(isr);
while(sCadena != null)
{
sCadena = br.readLine();
txa.append(sCadena + "\n");
}
txa.append("finished\n");
sck.close();
}
}
catch(Exception ex)
{
txa.append(ex.getMessage() + "\n");
ex.printStackTrace();
}
}
void cmdClose_actionPerformed(ActionEvent e)
{
try
{
sck.setSoLinger(true, 50);
sck.close();
txa.append("closed\n");
}
catch(Exception ex)
{
txa.append(ex.getMessage() + "\n");
ex.printStackTrace();
}
}
}
(Review ID: 130207)
======================================================================
Name: nt126004 Date: 08/20/2001
java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
1- Start a server listening for incoming socket connections.
2- Start a client connecting to the above server.
3- The client writes to the socket, the server reads from the socket.
4- At some point, the server closes the socket.
5- The first client write + flush after server socket closing does not report
any failure. Most of the time (but some times we have to wait for the third
write + flush) the second write throws an exception: "java.net.SocketException:
Connection aborted by peer: socket write error", which we think should be
reported by the first write + flush operation.
Here is the source code we wrote to simply reproduce the problem:
import java.io.*;
import java.net.*;
public class TestSocket
{
/**
* The main routine.
*/
public static void main(String strArguments[]) throws Exception
{
//
// Create the server
//
ServerSocket server = new ServerSocket(25000);
//
// Create and start the client thread.
//
Thread thread = new ClientThread();
thread.start();
//
// Read info coming from the client.
//
Socket socket = server.accept();
InputStream in = socket.getInputStream();
for (int i = 1; i <= 5; i++)
{
System.out.println("Read attempt " + i + ": " + in.read());
}
//
// Close everything.
//
in.close();
socket.shutdownInput();
socket.shutdownOutput();
socket.close();
server.close();
System.out.println("Socket closed on server side");
//
// Wait for client thread to end.
//
thread.join();
System.out.println("Exiting...");
}
/**
* The client thread.
*/
private static class ClientThread extends Thread
{
public void run()
{
try
{
Socket socket = new Socket("localhost", 25000);
OutputStream out = socket.getOutputStream();
for (int i = 1; i <= 1000; i++)
{
System.out.println("Write attempt " + i);
out.write(0);
out.flush();
Thread.sleep(5000);
}
out.close();
socket.close();
}
catch (Exception exception)
{
exception.printStackTrace();
}
}
}
}
The output of this program is the following:
Write attempt 1
Read attempt 1: 0
Write attempt 2
Read attempt 2: 0
Write attempt 3
Read attempt 3: 0
Write attempt 4
Read attempt 4: 0
Write attempt 5
Read attempt 5: 0
Socket closed on server side
Write attempt 6
Write attempt 7
java.net.SocketException: Connection aborted by peer: socket write error
at java.net.SocketOutputStream.socketWrite(Native Method)
at java.net.SocketOutputStream.write(SocketOutputStream.java:62)
at com.temenos.icc.ifc.net.TestInterruptableSocket$ClientThread.run
(TestInterruptableSocket.java:80)
Exiting...
(Review ID: 130300)
======================================================================