Problem with C server socket connected to Java client - java

I am writing an application on Android, and I want it to be able to know when the server (which I have written in C) dies or is shutdown. I am trying to implement this by having the server send a message to the client (the Android app) at a specified interval. If this message doesn't come, then the client knows that it is no longer connected to the server. They communicate using TCP sockets.
My problem is that the Android app cannot seem to read what the server writes. When it gets to the first part of the code where it tries to read from the server socket, it just hangs. In the Android app I am using a BufferedReader to read from the socket tmpstr = inFromServer.readLine(); where tmpstr is a string and inFromServer is the BufferedReader, and the C server is just using write write(newsockfd,"I got your message",18);.
I also tried using an alternative java server to see if my basic program logic was wrong. The test server used a PrintWriter, and it worked perfectly with the Android client.
What am I missing here? Is there a difference in the way Java and C buffer (or don't buffer) their data? If I need to give any additional information, please let me know.
Edit: I also have no trouble getting the C server to read data sent from the client. I only have trouble with getting the client to read data that is sent from the server.
Edit: The problem was fixed by adding a newline character (\n) to what the server sends to the client.

If I recall correctly, readLine() is not going to return the result until it has read a full line. It is going to block until then. You are not sending a full line from the C program.
Not only are you not sending a full line (\n terminated), but you also aren't even sending your entire C string since you're not sending the null terminator (Your C string actually contains 19 characters, not 18, if you include the null terminator). I don't recall what type of string format Java uses, if it's null terminated or not, but that part probably doesn't matter since it's looking for a \n, not a \0.
Try sending "I got your message\n" from the C server and let us know what happens then.
Oops, I just realized that the question had already been answered in the comments to it. Oh well. People really should post answers as answers.

Related

Open more than one stream between socket and serversocket

I'm creating a simple chat in Java, and it works. I just have a problem when a client close the connection, because it continue to appear online. This is because there's no a way to know when a stream is closed.
I searched on google and any solution has not resolved my problem, so I want to send a boolean each 300ms and, if I don't receive any answer or I get an error, I can close the connection server side.
The problem is that there's a conflict in the stream, I can't know if I'm reading a boolean or a text, so sometimes my CheckConnection class try to read a string and my SocketHandler class try to read a boolean, and I receive an error.
I use the class ObjectInputStream and ObjectOutputStream to read and write into the stream.
It's my first server application and I don't know very much about it, I don't know if it's possible open more than one stream or if there are other solutions, so I'm asking you. What may I do?
PS: I tried to create a PrintStream and execute the checkError() method, but it returns always false, even if I close explicitly all the streams client side. Thank you.
I suggest you use text as this is simpler to work with to start with.
treat any message as a heartbeat. If you get data, the connection is still good.
treat a heartbeat as a string and chat as a string. it's all a String so you don't need to worry about what it is.
check a stream is open by attempting to read from it and expecting you will get something within a timeout period.
You can use BufferedReader, or Scanner to reads the text. You can user BufferedWriter to write the text.
In your string you can create a simpler protocol like this.
say [to-whom] [message ...]
for the heartbeat you can have
hb
or
heartbeat
or
say nobody hi
You might add commands like
login [user] [password]
and
kthxbye
To decode the message, look at the first word and you know it's purpose and then read the second word for say and the rest of the string is the message.
To test the protocol, you can telnet to the port and type in stuff to the server directly. You don't even need to write a client to start with.

Java Server Socket with Client in C

I have written the server socket code in java. The relevant lines are:
byte[] bRecieved = new byte[440] ;
1int i =in.read(bRecieved);
Arrays.toString(bRecieved);
This works fine if the client is written in java
byte[] bSend = {1,2,3,4};
DataOutputStream out =
new DataOutputStream(outToServer);
out.write(bSend);
But the Client is written in C++. The code for sending is:
if (client.connect(serverIP, serverPort)) {
String msg="Hello Server";//Message to be sent
client.println(msg);//send the message
}
My question is , how do I communicate with the java server wanting bytes? The connection is successful and bytes are printed on the server console. But they are not "Hello Server". Do I have to iterate through the bytes and interpret them as chars? Chars and int are 1 byte in c++.
Please clarify this situation if possible.
Thanks in advance!
What library are you using for your C++ sockets?
You might try flushing the stream?
The C++ client is line-buffered by default. This means it won't actually send the data until either a newline is pushed onto the outbound data or the buffer holding data to be sent fills beyond a certain point (system dependent). If you want to see this in action set your msg string to "Hello Server\n". Your data should be sent right away.
The flush() command says, "send all data now, regardless of how much is in the buffer." So you can choose to do one other the other, either call flush() or append a newline. Of course if you use the newline, the Java process will receive a newline character in addition to the string, which may or may not be what you want. Generally, when performing network operations, you want to call flush() whenever you're done adding things to the outbound buffer.

How to detect if a windows named pipe has been closed?

I've got a third party program which puts data into a windows named pipe.
I access the pipe with
String pipename = "\\\\.\\pipe\\the_pipe";
RandomAccessFile pipe = new RandomAccessFile(pipename, "r");
DataInputStream input = new DataInputStream(Channels.newInputStream(pipe.getChannel()));
So sometimes someone gets the 'perfect' idea to close the third party program before my small data converting tool which of course closes the pipe. When that happens, my tool writes down the last message received million times into the resultfile and successfully fills every hdd up to the last byte within hours, because I am not able to check if the pipe has been closed.
Things I've tried:
// checking file descriptor and file channel
if(!(pipe.getFD().valid() && pipe.getChannel().isOpen())) {
// quit
}
But both options do not trigger.
Is there a other way to access named pipes where such an information can be obtained?
Or do I have overlooked something?
When that happens, my tool writes down the last message received million times into the resultfile
Only if your tool ignores EOFExceptions and -1 return values from read().
I would recommend looking at JNA to access the named pipe directly. Yes, you can detect the pipe closure if you use JNA.
I have done so in a project called NuProcess available on github.com. Particularly, look at the com.zaxxer.nuprocess.windows package. Look at the WindowsProcess.createPipes() method for setting up pipes (the code creates both ends, you only need one).
On the read side, NuProcess is using Windows IOCompletionPorts for asynchronous I/O (in ProcessCompletions.java), which may be overkill for what you need (or not). But once you get your feet wet setting up the pipes, you should be able to figure it out from there reading the Microsoft API docs.

Creating sessions in java socket programming with one server and multiple clients

I am a novice programmer in java.
I have created a program which is similar to a chat application using socket programming.
I haven't used threads.
My question is:
Whenever a client1 wants to communicate to another client2 via the sever how can i know which client is communicating.
I thought if i could differentiate all clients from server side by using sessions it would be easier. Just a random thought.
why this question??
I want to know this because i have stored the adressess of clients in a file along with a sequence number to make the messages visible to the pair alone globally. Whenever a client sends a message it prefixes it with a sequence number which is got from the client1 client2 pair stored in that file.
Any help would be greatly appreciated. Im just a learner in java. I apologize for any obscurity in my question.
First of all, try to make a thread to open a socket because it helps in your GUI processing. And the point that you want to see client names can be done by this steps:-
Add an editbox and enter your name (client name) and send this name along with the message and at server-side, split message and name so that you can determine which message is sent by whom.
Ex:- Client name is Alex and the message is "hi" then the data which will be sent is something like "Alex+hi". Now split this message using split() function in java at the server-side.
Hope this encoding and decoding will help you.

Exceptions when reading protobuf messages in Java

I am using protobuf now for some weeks, but I still keep getting exceptions when parsing protobuf messages in Java.
I use C++ to create my protobuf messages and send them with boost sockets to a server socket where the Java client ist listening. The C++ code for transmitting the message is this:
boost::asio::streambuf b;
std::ostream os(&b);
ZeroCopyOutputStream *raw_output = new OstreamOutputStream(&os);
CodedOutputStream *coded_output = new CodedOutputStream(raw_output);
coded_output->WriteVarint32(agentMessage.ByteSize());
agentMessage.SerializeToCodedStream(coded_output);
delete coded_output;
delete raw_output;
boost::system::error_code ignored_error;
boost::asio::async_write(socket, b.data(), boost::bind(
&MessageService::handle_write, this,
boost::asio::placeholders::error));
As you can see I write with WriteVarint32 the length of the message, thus the Java side should know by using parseDelimitedFrom how far it should read:
AgentMessage agentMessage = AgentMessageProtos.AgentMessage
.parseDelimitedFrom(socket.getInputStream());
But it's no help, I keep getting these kind of Exceptions:
Protocol message contained an invalid tag (zero).
Message missing required fields: ...
Protocol message tag had invalid wire type.
Protocol message end-group tag did not match expected tag.
While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either than the input has been truncated or that an embedded message misreported its own length.
It is important to know, that these exceptions are not thrown on every message. This is only a fraction of the messages I receive the most work out just fine - still I would like to fix this since I do not want to omit the messages.
I would be really gratful if someone could help me out or spent his ideas.
Another interesting fact is the number of messages I receive. A total messages of 1.000 in 2 seconds is normally for my program. In 20 seconds about 100.000 and so on. I reduced the messages sent artificially and when only 6-8 messages are transmitted, there are no errors at all. So might this be a buffering problem on the Java client socket side?
On, let's say 60.000 messages, 5 of them are corrupted on average.
[I'm not really a TCP expert, this may be way off]
Problem is, [Java] TCP Socket's read(byte[] buffer) will return after reading to the end of the TCP frame. If that happens to be mid-message (I mean, protobuf message), parser will choke and throw an InvalidProtocolBufferException.
Any protobuf parsing call uses CodedInputStream internally (src here), which, in case the source is an InputStream, relies on read() -- and, consequently, is subject to the TCP socket issue.
So, when you stuff big amounts of data through your socket, some messages are bound to be split in two frames -- and that's where they get corrupted.
I'm guessing, when you lower message transfer rate (as you said to 6-8 messages per second), each frame gets sent before the next data piece is put into the stream, so each message always gets its very own TCP frame, i.e. none get split and don't get errors. (Or maybe it's just that the errors are rare and low rate just means you need more time to see them)
As for the solution, your best bet would be to handle the buffer yourself, i.e. read a byte[] from the socket (probably using readFully() instead of read() because the former will block until either there's enough data to fill the buffer [or a EOF is encountered], so it's kind of resistant to the mid-message frame end thing), ensure it's got enough data to be parsed into a whole message, and then feed the buffer to the parser.
Also, there's some good read on the subject in this Google Groups topic -- that's where I got the readFully() part.
I am not familiar with the Java API, but I wonder how Java deals with an uint32 value denoting the message length, because Java only has signed 32-bit integers. A quick look at the Java API reference told me an unsigned 32-bit value is stored within a signed 32-bit variable. So how is the case handled where an unsigned 32-bit value denotes the message length? Also, there seems to be support for varint signed integers in the Java implementation. They are called ZigZag32/64. AFAIK, the C++ version doesn't know about such encodings. So maybe the cause for your problem might be related with these things?

Categories