PrintWriter println(String s) method: \r\n not supported? - java

I'm creating a multithread chat client server application.
In the server connection I use PrintWriter println(String s) method to write the response to the client.
PrintWriter out;
String msg = in.readLine();
String response = "";
if (msg.startsWith("nick: ") {
response = protocol.authenticate(msg); //returns a String that says "welcome " + nick
//if there are messages pending for the author who logged in add them to the response String
response+="\r\n"+textmsg;
} else { ... }
out.println(response);
When I run the client, who uses the BufferedReader readLine() method to read from the server, I get the welcome message but not the pending message for the client, but If I use
response+=textmsg;
it works, so I assume it's because I'm using \r\n but I still need to print a new line between those two messages. What should I do?
Edit after accepting the answer: In the end I chose to use OutputStream and InputStream so I can send every kind of string I want, even with \r\n.

Either call println once for each line of output (so twice) or use only \n, without the \r. That's Java's standard newline char and \r\n is a Windows-specific end-of-line sequence. Of course, at the client end you now have to call readLine twice as well. There is no way to call readLine once and get two lines. If you need a custom delimiter, then you must use something else, not \n.

Use println with PrintWriter, for the \n.

Related

Buffered Writer - Writing strings with "\n" inside

I was wondering if it's possible to send a single string with newline characters using BufferedWriter.
For context I need to send the following string over the network:
String message = "LOOKREPLY\nX...X\n.....\n.....\n.....\nX...X"
socketOutput = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
socketOutput.write(message + "\n");
But this sends 6 messages over the network because of the newline characters. I could re-build it on the client side but was wondering if there's a neater/simpler approach.
In your code
bw.write(message+"\n");
As it will put \n after all message has been written.
BufferedWriter will not send 6 Messages it will send only one but as you gave \n in your string it will write according to that.
As delv said you can put escape sequence to the \n so that it will write only one line.
String message = "LOOKREPLY\\nX...X\\n.....\\n.....\\n.....\\nX...X";
So that message will be written like this.
LOOKREPLY\nX...X\n.....\n.....\n.....\nX...X

Issue with loop and BufferedReader

I'm getting an strange issue in a loop that is reading a BufferedReader and never ends...
This is the code:
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
int b;
StringBuilder buff = new StringBuilder();
while ((b = in.read()) != -1 ) {
buff.append((char) b);
}
System.out.println(buff.toString());
But never arrives to the last line to print buff.toString().
There's anything wrong in this code?
Thanks.
Can you try changing the while condition like this.
while ((b = in.read()) > -1 ) {
buff.append((char) b);
}
Your loop is trying to read until EOF (that is the only reason for an input stream/reader to return -1 for the read() method).
The problem is that your HTTP connection (and your socket) might be left open (for a while), also leaving your input stream/reader open. So instead of reaching the end condition for your loop, the in.read() call will just block, waiting for input.
If you control the "other side" of the connection, you could close it, to see what happens. But I doubt that would work for the use case in general. Instead, you need to parse the message according to the HTTP protocol (see HTTP/1.1 RFC2616).
If you only need to parse the headers, then you could use your BufferedReader, and read only full lines, until you find an empty line. This will work, because HTTP uses linefeeds (linefeed being CRLF in this case) after each header name/value pair, and end the header part with exactly two linefeeds. Everything after that will be the message body.
PS: This is the easy/happy case. Note that a single connection/socket may be re-used for multiple HTTP requests/responses. You may have handle this as well, depending on your requirements.

Netty FrameDecoder not invoked in ChannelPipeline without carriage return?

I'm working with Netty and it seems that a FrameDecoder in a ChannelPipeline isn't invoked unless/until a carriage return is received. For example, I have the following decoder that I've written to attempt to detect when a complete JSON string has been received:
public class JsonDecoder extends FrameDecoder {
#Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buf) {
char inChar = 0;
ChannelBuffer origBuffer = buf.copy();
StringBuilder json = new StringBuilder();
int ctr = 0;
while(buf.readable()) {
inChar = (char) buf.readByte();
json.append(inChar);
if (inChar == '{') {
ctr++;
} else if (inChar == '}') {
ctr--;
}
}
if (json.length() > 0 && ctr == 0) {
return origBuffer;
}
buf.resetReaderIndex();
return null;
}
}
(Please pardon the somewhat sloppy code - this is my first attempt using Netty and a bit of a learning experience.)
What I see happen is that this works fine when I test it by connecting to the server using telnet, paste in some valid JSON and press return. However, if I do not press return after the final closing '}' in the JSON string, the decoder never gets called with an updated buffer.
Is there a way to configure the channel pipeline to work differently? I've Googled for this and looked through the Netty documentation. I feel like I'm missing something basic and I just am not looking in the right place or searching for the right thing. Thanks for any help.
Is your telnet client reverting to 'old line by line' mode whereby only completed lines are sent to the server (telnet man page)? Try writing a simple Java client to send the message instead.
I guess reading a JSON stream is more akin to reading an HTTP stream, since you will have to keep track of the opening and closing braces (and brackets as well, should the JSON string be an array). If you look at the source for the HTTP decoder, you'll see that it is using a ReplayingDecoder. Using a replaying decoder is not necessary, but it helps a lot if the entire message is split in more than one buffer.
FrameDecoders are meant for reading messages that are "framed" by special characters (hence the name of the decoder) or prepended with a length field.
I would also highly recommend using the DecoderEmbedder helper class so that you can unit test your JSON decoder without doing actual I/O.

Is BufferedReader ignoring the first line?

I am currently writing a service that should take cleartext commands and then return something according to thoose commands, which is also in cleartext.
I have this odd problem with BufferedReader, or, it might be telnet that is odd, for some reason the BufferedReader reads the first command, however that command is ignored no matter what i do, which i can get around by sending the first command twice, but that is just stretching it a bit, in my oppinion.
The code below is in a run() method.
Then i set out as a PrintWriter and in as a BufferedReader.
The runs variable is by default true.
out = new PrintWriter(handle.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(handle.getInputStream()));
while (runs) {
String msg;
msg = in.readLine();
String[] command;
command = msg.split(" ", 3);
/* do something with the command */
}
So my question is if BufferedReader is ignoring the first line or is it telnet that is not coorperating with me?
If it is something else, then please enlighten me.
EDIT
I got this debug message:
Debug: ���� ����'������/nick halmark
so i suppose that it is about all the questionmarks.
I am actually using the latest Putty since i am developing on a windows box... and as far as i recall... then it does not exist by default
If you are using PuTTY, you need to choose the "Raw" Connection Type.
Microsoft telnet servers like to have some content/protocol negotiation at the beginning, so PuTTY will do this by default as per the RFC 854 spec. That's the garbage that you are reading.

Client-side string encoding java

My team and I have this nasty problem with parsing a string received from our server. The server is pretty simple socket stuff done in qt here is the sendData function:
void sendData(QTcpSocket *client,QString response){
QString text = response.toUtf8();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << (quint32)0;
out << text;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));
try{
client->write(block);
}
catch(...){...
The client is in Java and is also pretty standard socket stuff, here is where we are at now after trying many many different ways of decoding the response from the server:
Socket s;
try {
s = new Socket(URL, 1987);
PrintWriter output = new PrintWriter(s.getOutputStream(), true);
InputStreamReader inp = new InputStreamReader(s.getInputStream(), Charset.forName("UTF-8"));
BufferedReader rd = new BufferedReader( inp );
String st;
while ((st = rd.readLine()) != null){
System.out.println(st);
}...
If a connection is made with the server it sends a string "Send Handshake" with the size of the string in bytes sent before it as seen in the first block of code. This notifies the client that it should send authentication to the server. As of now the string we get from the server looks like this:
������ ��������S��e��n��d�� ��H��a��n��d��s��h��a��k��e
We have used tools such as string encode/decode tool to try and assess how the string is encoded but it fails on every configuration.
We are out of ideas as to what encoding this is, if any, or how to fix it.
Any help would be much appreciated.
At a glance, the line where you convert the QString parameter to a Utf8 QByteArray and then back to a QString seems odd:
QString text = response.toUtf8();
When the QByteArray returned by toUtf8() is assigned to text, I think it is assumed that the QByteArray contains an Ascii (char*) buffer.
I'm pretty sure that QDataStream is intended to be used only within Qt. It provides a platform-independent way of serializing data that is then intended to be deserialized with another QDataStream somewhere else. As you noticed, it's including a lot of extra stuff besides your raw data, and that extra stuff is subject to change at the next Qt version. (This is why the documentation suggests including in your stream the version of QDataStream being used ... so it can use the correct deserialization logic.)
In other words, the extra stuff you are seeing is probably meta-data included by Qt and it is not guaranteed to be the same with the next Qt version. From the docs:
QDataStream's binary format has evolved since Qt 1.0, and is likely to
continue evolving to reflect changes done in Qt. When inputting or
outputting complex types, it's very important to make sure that the
same version of the stream (version()) is used for reading and
writing.
If you are going to another language, this isn't practical to use. If it is just text you are passing, use a well-known transport mechanism (JSON, XML, ASCII text, UTF-8, etc.) and bypass the QDataStream altogether.

Categories