I've got the following code, I'm trying to send data text by sockets. But when I try to send via PrintWriter, my client does nothing and it stops at in.readLine(). However when I use simply OutputStream and send it as bytes, my client doesn't have any problem with reading. Is it possible to as I want ?
out = new PrintWriter(sock.getOutputStream());
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
while (true) {
System.out.println("SERVER-THREAD: IP "
+ sock.getInetAddress().getHostAddress());
out.write(marshall() + "\n");
Thread.sleep(1000);
}
//Client
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
out = new PrintWriter(sock.getOutputStream());
while (updateList) {
System.out.println("Before");
String inputip = in.readLine();
System.out.println("CLIENT: " + inputip);
//unmarshall(in);
System.out.println("After");
Thread.sleep(1000);
}
PrintWriter buffers the data to be written so it will not do so until the buffer is full. You need to call flush here
out.flush();
When you perform a readLine() it waits until it has a read a whole line. i.e. a new line.
Your send is sending text without a newline so the receive waits for something which will not happen.
A more basic problem is that you are mixing text and binary which is more likely to confuse than be useful.
I suggest you write text with PrintWriter.println() which you can read with BufferedReader.readLine().
Related
This is a a Java method that tries to crawl a designated web page. I am using writeUTF and readUTF for socket communications to a server.
static void get_html(String host, String page, int port) throws IOException {
Socket sock = new Socket(host, port);
String msg = MessageFormat.format("GET {0} HTTP/1.1\r\nHost: {1}\r\n\r\n", page, host);
DataOutputStream outToServer = new DataOutputStream(sock.getOutputStream());
DataInputStream inFromServer = new DataInputStream(sock.getInputStream());
InputStream stream = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8));
BufferedReader buf = new BufferedReader(new InputStreamReader(stream));
String outMsg;
while ((outMsg = buf.readLine()) != null) {
System.out.println("Sending message: " + outMsg);
outToServer.writeUTF(outMsg);
String inMsg;
try {
inMsg = inFromServer.readUTF();
} catch (EOFException eof) {
break;
}
System.out.println(inMsg);
}
sock.close();
}
The reason I am writing it this way was to mimic the c code, where you have a while loop of send() making all deliveries from a buffer, and another while loop of recv() from a buffer untill it hits 'null'. When execute my code, it just hangs there, I suspect that is due to a call of readUTF before I finished sending all my messages. If this is the case, is there any way to fix it?
You can't do this. HTTP is defined as text lines. writeUTF() does not write text, it writes a special format starting with a 16-bit binary length word. Similarly the HTTP server won't reply with that format into your readUTF() call. See the Javadoc.
You have to use binary streams and the write() method, with \r\n as the line terminator. Depending on the output format you may or may not be able to use readLine(). Best not, then you don't have to write two pieces of code: use binary streams again.
In fact you should throw it all away and use HttpURLConnection. Implementing HTTP is not as simple as may hastily be supposed.
I have client code that looks like:
Socket s = new Socket(server.getHostName(), server.getPort());
PrintWriter p = new PrintWriter(s.getOutputStream());
p.println(message);
p.flush();
s.shutdownOutput();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String newLine;
StringBuffer response = new StringBuffer();
while((newLine = br.readLine()) != null)
response.append(newLine);
System.out.println(response.toString());
p.close();
br.close();
and server code that looks like:
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String nextLine;
StringBuffer request = new StringBuffer();
System.out.println("Starting read....");
String nextline;
while((nextline = br.readLine()) != null){
System.out.println(nextline);
request.append(nextline);
}
System.out.println("Message recived!!");
System.out.println("Request: " + request);
PrintWriter p = new PrintWriter(s.getOutputStream());
p.println("Hello, fileclient!");
System.out.println("Message sent!!");
p.close();
br.close();
Before I put the line s.shutDownInput() the server code would hang at br.readLine(). The way I managed to fix that is to close the PrintWriter some how, either through p.close() or through the current way which doesn't
shutdown the socket like closing the PrintWriter through p.close() does. After that, the interaction between client and server is perfect.
Why does the PrintWriter or the BufferedReader not send/receive until the PrintWriter is closed somehow?
It doesn't have anything to do with PrintWriter. It is an application protocol error on your part.
The server is looping reading lines until end of stream.
The client is sending one line and then not closing the socket, so no end-of-stream got sent (until you added the shutdown).
The server is then responding.
The client is then reading.
So the client doesn't read anything until the server gets out of the loop, and the server doesn't get out of its loop because the client is reading not closing.
So make up your mind. Probably the server should only read one line.
Both sides are behaving exactly as you told them to do. In particular, you instruct the server specifically to read everything the client sends before dispatching any response:
String nextline;
while((nextline = br.readLine()) != null){
System.out.println(nextline);
request.append(nextline);
}
It is important to understand that that will not stop reading until an error or end of stream, where end of stream on a socket corresponds to the other end having been closed and all data having been read. In other words, your server waits for the end of the whole conversation, not the end of a single message, before dispatching a response.
Since that's apparently not what you want, you need to implement a different strategy at the server for determining when to process the data received so far and send a response. If you can be confident that your messages will not contain internal newlines, then that might be as simple as the server performing only one br.readLine() before sending each response.
I got a server waiting for messages and a client sending him messages, when using
PrintWriter out = new PrintWriter(lpSocket.getOutputStream(), true);
String msg;
BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
while ((msg = userIn.readLine()) != null)
out.print(msg + (char) 10);
nothing happens, meaning the server just keep waiting for a message that never arrive. When I change the out.print to out.println it works.
I would like to know why
By default, PrintWriter calls flush in println, whereas it doesn't do this in print. You can fix this by adding out.flush() after your out.print call
I am trying to have my client connect to my server, and depending on the command send some string back to the client. Currently the app connects and can send strings to the server very nicely. However when I send the command which instructs the server to send something back it hangs. I found that the problem occurs when the client attempts to read the line send from the server.
Server
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
out.println("GETDATA" + "\n");
out.flush();
out.close();
Client
BufferedReader fromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
incomingLine = fromServer.readLine();
Log.d("HERE", "NOT " + incomingLine);
fromServer.close();
Thanks!
I made effectively this same mistake when I was first doing sockets as well.
Don't use PrintWriter with BufferedReader. They're incompatible. By comments, PrintWriter actually hides critical exceptions, so they shouldn't be used in networking. Instead, use a DataInputStream and DataOutputStream for communications.
client = new Socket(hostname, port);
inStr = new DataInputStream(client.getInputStream());
outStr = new DataOutputStream(client.getOutputStream());
Then, send and receive using writeUTF and readUTF, like so:
public void send(String data) throws IOException {
outStr.writeUTF(data); outStr.flush();
}
public String recv() throws IOException {return inStr.readUTF();}
The reason has to do with the UTF encoding; a BufferedReader expects a certain string encoding, which PrintWriter does not give. Thus, the read/write hangs.
The method readLine() expects an end of line character "\n" maybe that's your problem
I have the basic code for a server:
ServerSocket serverSocket = new ServerSocket(14000);
Socket clientSocket = serverSocket.accept();
BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(clientSocket.getOutputStream());
String incoming;
while((incoming = in.readLine()) != null){
System.out.println("Client Says: " + incoming);
out.println("Client Says: " + incoming);
out.flush();
//if(incoming.equals("HELLO")) break;
}
clientSocket.close();
serverSocket.close();
I'm trying to further understand streams as they're giving me some serious headaches. From what I've read, println methods automatically flush for you, however this line is not delivered to the client unless the flush method is called afterwards? I'm just looking for a nice solid explanation of this?
To enable automatic flushing of the PrintWriter, the second argument of its constructor must be set to true.
I had this issue before, just:
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
That will make the difference. If you do not autoflush you can get some errors or receive data as null, it happened to me some time ago. Best regards.