Help needed with ServerSocket. What's wrong in my code ?

D

David Bouchard

Hi,

I'm trying to do a very simple client/server application :
I have 2 text fields and a button in a jframe
The first textfield is editable whereas the second is not.
i want to send what's typed in the first textfield to the server when
the user clicks the button. the server then modifies slightly the
string and sends it back to the client. the client then displays the
string it received from the server into the second textfield

when i run the code below, the server does not receive any string and i
really don't know why...

could someone help ?
thanks !
David.

PS : I know the in.readLine() are useless here but this is a test
application and in my 'real' application I will need them so they must
be used here.
PS 2 : if I uncomment the line //out.close(); in the method
sendAndReceive, the server gets the string from the client but then
fails to respond
(sendAndReceive : error java.net.SocketException: socket closed)

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.apache.log4j.Logger;

public class TestSocket
{
public static void main(String[] args)
{
launchServer();

JFrame frame = new JFrame("Client");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

final JTextField tfSend = new JTextField();
final JTextField tfReceived = new JTextField();
tfReceived.setEditable(false);
JButton boutonEnvoi = new JButton("Send");
boutonEnvoi.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
sendAndReceive(tfSend, tfReceived);
}
});

JPanel tfPanel = new JPanel(new GridLayout(2,2));
tfPanel.add(new JLabel("Send"));
tfPanel.add(tfSend);
tfPanel.add(new JLabel("Received"));
tfPanel.add(tfReceived);

JPanel mainPanel = new JPanel(new BorderLayout());
mainPanel.add(tfPanel, BorderLayout.CENTER);
mainPanel.add(boutonEnvoi, BorderLayout.SOUTH);

frame.setContentPane(mainPanel);
frame.setSize(250, 100);
frame.setVisible(true);
}

public static void launchServer()
{
Thread t = new Thread()
{
public void run()
{
try
{
ServerSocket ss = new ServerSocket(12012);
System.out.println("[SERVER] started");
for ( ; ; )
{
Socket s = ss.accept();
System.out.println("[SERVER] client connexion");
dealConnexion(s);
}
}
catch (IOException e)
{
System.err.println("run : error : "+e);
e.printStackTrace();
}
}

public void dealConnexion(final Socket s)
{
Thread t = new Thread()
{
public void run()
{
try
{
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));
PrintWriter out =
new PrintWriter(s.getOutputStream());

// read from client
StringBuffer sb = new StringBuffer();
String ligne = null;
sb.setLength(0);
while ((ligne = in.readLine()) != null)
{
sb.append(ligne);
System.out.println("[SERVER] received line '"
+ligne+"'");
}
System.out.println("[SERVER] received '"
+ sb.toString()+"'");

// write to client
out.println("You sent '" + sb.toString() + "'");
}
catch (IOException e)
{
System.err.println("gererConnexion : error : "+e);
e.printStackTrace();
}
}
};
t.start();
}
};
t.start();
}

public static void sendAndReceive(final JTextField toSendTF,
final JTextField receivedTF)
{
Thread t = new Thread()
{
public void run()
{

try
{
Socket s = new Socket("127.0.0.1", 12012);
PrintWriter out = new PrintWriter(s.getOutputStream());
BufferedReader in = new BufferedReader(
new InputStreamReader(s.getInputStream()));

StringBuffer sb = new StringBuffer();
String line = null;

// send what's in text field toSendTF to server
String txt = toSendTF.getText();
if ( null==txt || txt.length()==0 )
{
System.err.println("[CLIENT] nothing to send!");
return;
}
toSendTF.setText(null);
System.out.println("[CLIENT] sends ["+txt+"]");
out.println(txt);
//out.close();
toSendTF.setText(null);

// read response from server
sb.setLength(0);
while ((line = in.readLine()) != null)
{
sb.append(line);
System.out.println("[CLIENT] gets line ["+line+"]");
}
System.out.println("[CLIENT] received '"+sb.toString()+"'");
receivedTF.setText(sb.toString());

s.close();
}
catch (Exception e)
{
System.err.println("sendAndReceive : error "+e);
e.printStackTrace();
}
}
};
t.start();
}
}
 
M

Matt Humphrey

David Bouchard said:
Hi,

I'm trying to do a very simple client/server application :
I have 2 text fields and a button in a jframe
The first textfield is editable whereas the second is not.
i want to send what's typed in the first textfield to the server when
the user clicks the button. the server then modifies slightly the
string and sends it back to the client. the client then displays the
string it received from the server into the second textfield

when i run the code below, the server does not receive any string and i
really don't know why...

You probably need to flush the output. out.flush ().

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
D

David Bouchard

I've replaced
new PrintWriter([OutputStream])
with
new PrintWriter([OutputStream], true)
which means that automatic flushing is enabled (only when println() is
used though, which is the case uin my code)

Now, I get the following output :
[SERVER] started
[SERVER] client connexion
[CLIENT] sends [qqq]
[SERVER] received line 'qqq'

-> Server gets the line sent by the client but never exits the
following loop :
while ((ligne = in.readLine()) != null)
{
sb.append(ligne);
System.out.println("[SERVER] received line '"
+ligne+"'");
}

As i never get the "[SERVER] received 'xxxx'" output.
Any idea ?
 
M

Matt Humphrey

David Bouchard said:
I've replaced
new PrintWriter([OutputStream])
with
new PrintWriter([OutputStream], true)
which means that automatic flushing is enabled (only when println() is
used though, which is the case uin my code)

Now, I get the following output :
[SERVER] started
[SERVER] client connexion
[CLIENT] sends [qqq]
[SERVER] received line 'qqq'

-> Server gets the line sent by the client but never exits the
following loop :
while ((ligne = in.readLine()) != null)
{
sb.append(ligne);
System.out.println("[SERVER] received line '"
+ligne+"'");
}

As i never get the "[SERVER] received 'xxxx'" output.
Any idea ?

The in.readLine () will wait indefinately for more characters--it doesn't
return null simply because there's nothing there right now. Client closing
the stream will make it return null, but that's probably not what you want.
If you're planning on using the same connection for multiple requests you
need a way to delimit the requests, e.g. one per line, fixed buffer size,
4-byte buffer prefix followed by fixed buffer size, a language of some kind
(e.g. xml) or whatever. If you're happy with one request per connection,
just read and close the connection. For a simple protocol either one
request per connection or one request per line is very reasonable.

Cheers,
Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
H

Harald

David Bouchard said:
-> Server gets the line sent by the client but never exits the
following loop :
while ((ligne = in.readLine()) != null)
{
sb.append(ligne);
System.out.println("[SERVER] received line '"
+ligne+"'");
}

Yeah, typical problem. The readLine returns null only when the client
closes the connection. But don't call close() on the OutputStream in
the client, because this will shutdown the whole socket, preventing
your client to read the data from the server.

What you want is socket.shutdownOutput() in the client.

Try
http://www.ebi.ac.uk/Rebholz-srv/whatizit/monq-doc/monq/net/TcpServer.html
on the server side or download and explore the code. I think I got it
almost right.

Have fun,
Harald.
 
D

Dale King

David said:
I've replaced
new PrintWriter([OutputStream])
with
new PrintWriter([OutputStream], true)
which means that automatic flushing is enabled (only when println() is
used though, which is the case uin my code)

Now, I get the following output :
[SERVER] started
[SERVER] client connexion
[CLIENT] sends [qqq]
[SERVER] received line 'qqq'

-> Server gets the line sent by the client but never exits the
following loop :
while ((ligne = in.readLine()) != null)
{
sb.append(ligne);
System.out.println("[SERVER] received line '"
+ligne+"'");
}

As i never get the "[SERVER] received 'xxxx'" output.
Any idea ?

The server is only going to exit that loop when it gets an EOF which
will only happen if the client closes the connection. In your case it
will just block waiting on the client to send more data.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top