Reputation: 1938
I want to write a socket client to send a request to a server and get response back. It works, but not right. Here is my code:
public String send(final String data) {
Socket client = null;
String response = null;
try {
client = new Socket(this.host, this.port);
final OutputStream outToServer = client.getOutputStream();
final DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF(data);
final InputStream inFromServer = client.getInputStream();
final DataInputStream in = new DataInputStream(inFromServer);
response = in.readUTF();
} catch (final IOException e) {
this.log.error(e);
this.log.error("Sending message to server " + this.host + ":" + this.port + " fail", e);
} finally {
if (client != null) {
try {
client.close();
} catch (final IOException e) {
this.log.error("Can't close socket connection to " + this.host + ":" + this.port, e);
}
}
}
if (StringUtils.isBlank(response)) return null;
return response;
}
The problem is: I didn't got the full response with in.readUTF()
. I always got a response with the same length as the sent data's length (variable data
). I have tested with other GUI client and got the full response. So it's not a problem of the server.
Does someone known, what i did wrong?
UPDATE
Thanks EJP and Andrey Lebedenko. I think, my problems are the functions writeUTF
and readUTF
. So i have edited my code in the try
block so:
Charset charset = Charset.forName("ISO-8859-1");
final OutputStream outToServer = client.getOutputStream();
final DataOutputStream out = new DataOutputStream(outToServer);
out.write(data.getBytes(charset));
final InputStream inFromServer = client.getInputStream();
final BufferedReader in = new BufferedReader(new InputStreamReader(inFromServer, charset));
response = in.readLine();
And it worked now.
Upvotes: 0
Views: 5956
Reputation: 1988
Without knowing what does server part do, it is kind of difficult (if possible at all) to trace down the root cause. So in the most honest hope that it will help I just share this code with which I've tested the fragment above.
package tcpsendreceive;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SendReceive {
private static final Logger log = Logger.getLogger(SendReceive.class.toString());
private final String host;
private final int port;
private Server server;
class Server extends Thread
{
private final ServerSocket serverSocket;
public Server(ServerSocket s)
{
serverSocket = s;
}
@Override
public void run()
{
Socket connection;
SendReceive.this.log.log(Level.INFO, "Server: DoubleEcho Server running on "+this.serverSocket.getLocalPort());
try{
do {
connection = this.serverSocket.accept();
SendReceive.this.log.log(Level.INFO, "Server: new connection from "+connection.getRemoteSocketAddress());
int b;
do {
DataInputStream in = new DataInputStream(connection.getInputStream());
String s = in.readUTF();
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
out.writeUTF(s+","+s); // echo it back TWICE
out.flush();
connection.shutdownOutput();
connection.close();
} while(!connection.isClosed());
}
while(true);
}
catch(IOException ioe)
{
SendReceive.this.log.log(Level.SEVERE, "IOException in server! - STOP", ioe);
}
finally {
try{
this.serverSocket.close();
} catch (Exception e) {
SendReceive.this.log.log(Level.SEVERE, "IOException closing server! - FATAL", e);
}
try{
if(!connection.isClosed())
connection.close();
} catch (Exception e) {
SendReceive.this.log.log(Level.SEVERE, "IOException closing server! - FATAL", e);
}
}
}
}
public SendReceive(String host, int port)
{
this.host = host;
this.port = port;
try{
this.server = new Server(new ServerSocket(this.port));
this.server.start();
}
catch(IOException ioe)
{
this.log.log(Level.SEVERE, "IOException while creating server! - STOP", ioe);
}
}
public String send(final String data) {
Socket client = null;
String response = null;
try {
client = new Socket(this.host, this.port);
final OutputStream outToServer = client.getOutputStream();
final DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF(data);
final InputStream inFromServer = client.getInputStream();
final DataInputStream in = new DataInputStream(inFromServer);
response = in.readUTF();
} catch (final IOException e) {
this.log.log(Level.SEVERE, "Sending message to server " + this.host + ":" + this.port + " fail", e);
} finally {
if (client != null) {
try {
client.close();
} catch (final IOException e) {
this.log.log(Level.SEVERE, "Can't close socket connection to " + this.host + ":" + this.port, e);
}
}
}
if(response == null || response.isEmpty())
return null;
return response;
}
}
Test-demo
package tcpsendreceive;
public class Main {
public static void main(String[] args)
{
String data = "AAABBB";
SendReceive sr = new SendReceive("localhost", 5000);
String res = sr.send(data);
System.out.println("Sent: "+data);
System.out.println("Received: "+res);
}
}
Result (key part):
Sent: AAABBB
Received: AAABBB,AAABBB
Hope it helps.
EDIT 1. Corrected wrapper flush instead of socket stream flush. Still believe it is good practice to flush the stream wrapper before closing the socket.
P.s. I should admit I was bit surprised by such an attention to the humble test server code, especially compared to other dirty tests we all have seen on SO. Flattered. :)
Upvotes: 0
Reputation: 310957
If it works with Telnet, as per your comment, the server isn't using readUTF()
, so your writeUTF()
is already wrong, and the server is therefore unlikely to be using writeUTF()
either, which would make your readUTF()
wrong as well. You can't use these methods arbitrarily: they can only interchange data between themselves.
I'll bet your GUI client that works doesn't use them either.
Upvotes: 1