Socket communication between C and java - java

I have a client and a server both running in C. My task is to introduce java program in which I create a server to the C client and a client to the C server. I am successful in trying to get the connections set up properly. However the problem is in communicating the data between both C programs. Below is what I have written in my java program:
while(true){
while((userInput1=br1.readLine())!=null||(userInput2=br2.readLine())!=null){
if(userInput1=!null){
bw1.write(userInput1);
bw1.flush();
}
if(userInput2=!null){
bw2.write(userInput2);
bw2.flush();
}
}
While debugging the above, it is seen that the execution is stuck at the second while statement meaning that the input stream is waiting for the input for the C client for ever. I am using BufferedReader and BufferedWriter for the streams. The C client and server are using send and recv functions to communicate.
Kindly help with any inputs to make the java program help both the C programs communicate with each other as they do without this.

Have you correctly considered the effect of Java's "short circuit" or operator?
With || if the first clause is true the second is never evaluated.
while(
(userInput1=br1.readLine())!=null ||
(userInput2=br2.readLine())!=null) {
So you successfully read
userInput1=br1.readLine())!=null
and immediately enter your processing, then come back to while and read the next line into userInput1 again. Hence userInput2 never will receive a value.
You need separate logic like
read first line
read second line
But exactly what should you do when reading line2 and a the data is not ready? Try again? Is the line you read next the expected line2 or a new line1? This is quite tricky to get right.
I would prefer not to rely on two separate readlines in my protocol.

while((userInput1=br1.readLine())!=null||(userInput2=br2.readLine())!=null){
This condition means that you are going to read br1 all the way to EOS before you ever read anything from br2. Is that what you really intended?
Conversely, if you are stuck at br2.readLine() it means two things: (a) br1 is at EOS, and (b) the peer associated with br2 hasn't sent anything, or at least hasn't sent a line terminated by a newline.
Are you perhaps suffering from the common delusion that readLine() returns null when there is no data ready to be read?
Also you are reading lines terminated by newlines, which are removed by the readLine() call, and then writing them out without any newlines, which can hardly be correct.
It appears to me that what you are really writing is a proxy, in which case you need two threads per socket, one reading from A and writing to B, and the other reading from B and writing to A. And if it's a proxy you should use InputStreams and OutputStreams rather than Readers and Writers, as you probably have no reason to inspect the data, and you therefore shouldn't put it through the byte->char and char->byte conversion processes implied by using Readers and Writers. There are further subtleties when writing proxies but I'll wait for your confirmation before elucidating them.

the reason I am using the parity character is to interpret the end of the stream. Otherwise using using just the read() is making the program halt for the input forever (even after the actual had sent all its data). Am using the ready() in the following way:
//The proxy client
while(true){
if(br1.ready()){
while((temp1=br1.read())!=(int)par)
userInput1=userInput1+(char)temp1;
System.out.println("Input to Actual Server: " + userInput1);
bw1.write(userInput1);
bw1.flush();
System.out.flush();
userInput1="";
temp1=0;
}
if(br2.ready()){
while((temp2=br2.read())!=(int)par)
userInput2=userInput2+(char)temp2;
System.out.println("Response from Actual Server: " + userInput2);
userInput2=userInput2+par;
bw2.write(userInput2);
bw2.flush();
System.out.flush();
userInput2="";
temp2=0;
}
}
//The proxy server
while(true){
if(br1.ready()){
while((temp1=br1.read())!=(int)par)
userInput1=userInput1+(char)temp1;
System.out.println("Input from Actual Client: " + userInput1);
userInput1=userInput1+par;
bw1.write(userInput1);
bw1.flush();
System.out.flush();
userInput1="";
temp1=0;
}
if(br2.ready()){
while((temp2=br2.read())!=(int)par)
userInput2=userInput2+(char)temp2;
System.out.println("Response to Actual Client: " + userInput2);
bw2.write(userInput2);
bw2.flush();
System.out.flush();
userInput2="";
temp2=0;
}
}
Kindly suggest if there is any problem of using ready().

Related

HTTP Webserver ignoring last line of POST request [duplicate]

Right now, I'm trying to write a GUI based Java tic-tac-toe game that functions over a network connection. It essentially works at this point, however I have an intermittent error in which several chars sent over the network connection are lost during gameplay. One case looked like this, when println statements were added to message sends/reads:
Player 1:
Just sent ROW 14 COLUMN 11 GAMEOVER true
Player 2:
Just received ROW 14 COLUMN 11 GAMEOV
Im pretty sure the error is happening when I read over the network. The read takes place in its own thread, with a BufferedReader wrapped around the socket's InputStream, and looks like this:
try {
int input;
while((input = dataIn.read()) != -1 ){
char msgChar = (char)input;
String message = msgChar + "";
while(dataIn.ready()){
msgChar = (char)dataIn.read();
message+= msgChar;
}
System.out.println("Just received " + message);
this.processMessage(message);
}
this.sock.close();
}
My sendMessage method is pretty simple, (just a write over a DataOutputStream wrapped around the socket's outputstream) so I don't think the problem is happening there:
try {
dataOut.writeBytes(message);
System.out.println("Just sent " + message);
}
Any thoughts would be highly appreciated. Thanks!
As it turns out, the ready() method guaruntees only that the next read WON'T block. Consequently, !ready() does not guaruntee that the next read WILL block. Just that it could.
I believe that the problem here had to do with the TCP stack itself. Being stream-oriented, when bytes were written to the socket, TCP makes no guarantees as to the order or grouping of the bytes it sends. I suspect that the TCP stack was breaking up the sent string in a way that made sense to it, and that in the process, the ready() method must detect some sort of underlying break in the stream, and return false, in spite of the fact that more information is available.
I refactored the code to add a newline character to every message send, then simply performed a readLine() instead. This allowed my network protocol to be dependent on the newline character as a message delimiter, rather than the ready() method. I'm happy to say this fixed the problem.
Thanks for all your input!
Try flushing the OutputStream on the sender side. The last bytes might remain in some intenal buffers.
It is really important what types of streamed objects you use to operate with data. It seems to me that this troubleshooting is created by the fact that you use DataOutputStream for sending info, but something else for receiving. Try to send and receive info by DataOutputStream and DataInputStream respectively.
Matter fact, if you send something by calling dataOut.writeBoolean(b)
but trying to receive this thing by calling dataIn.readString(), you will eventually get nothing. DataInputStream and DataOutputStream are type-sensitive. Try to refactor your code keeping it in mind.
Moreover, some input streams return on invocation of read() a single byte. Here you try to convert this one single byte into char, while in java char by default consists of two bytes.
msgChar = (char)dataIn.read();
Check whether it is a reason of data loss.

How does a BufferedReader interact with a Socket? About how Sockets work

I have been following a tutorial on how to build a simple chat application in Java. I get the basic principle of how sever and client communicate. So far I used a PrintWriter to send, and a BufferedReader to recieve information for both sides. But what I don´t get is how this does not lead to errors?
Socket soc = new Socket(ipAddress, port);
BufferedReader in = new BufferedReader( new InputStreamReader(soc.getInputStream));
while(true) {
String str = in.readLine();
}
My question would be the following. Is the in.readLine() statement "waiting" for input? If it does not, shouldn´t the program throw Errors if using the str since it has no value? Or in general terms, do Socket specific functions like Socket soc = serverSocket.accept(); or as in the example given above the reading of an InputStream "wait" for a signal whatsoever? Did I miss some essential concept about Sockets? It would be great if someone could help me understand this topic further.
Thank you in advance,
Appa
My question would be the following. Is the in.readLine() statement "waiting" for input?
Yes, it is "waiting for input" since .readLine() is a blocking method
If it does not, shouldn´t the program throw Errors if using the str since it has no value?
I cannot parse this -- the statement doesn't make sense. What error / exception would you be expecting?
Or in general terms, do Socket specific functions like Socket soc = serverSocket.accept(); or as in the example given above the reading of an InputStream "wait" for a signal whatsoever?
Again, I'm afraid that this is not too clear (at least to me). ServerSocket#accept() is a blocking method and will wait until a socket connection can be made, if that is what you are asking.
Note that thiscode:
while(true) {
String str = in.readLine();
}
while valid, would not be particularly useful, since you would be reading a String and then discarding it, doing nothing with it. Better to either print the String obtained, or pass it into a method where it can be used in some way. On the other hand, I suppose this could be useful if all you wanted to do was to "gobble" the stream to prevent the OS's buffers from overflowing.
Yes readLine does in fact block. It waits till you read a carriage return/line feed, or the socket closes.

Can I write in the same socket using bufferedwriter and having threadsafe?

I have a client use a bufferedwriter for write in a socket. But client create a thread that can use the same bufferedwriter. I don't use lock for it and my program doesn't have problem, but have I a problem if the main thread of client and the thread of the client write in the bufferedwriter in the same time?
BufferedWriter's documentation does not describe its thread safety; the package-level documentation says nothing either.
Even if the individual methods were implemented atomically, calling multiple methods on the writer would definitely not be atomic.
You should err on the side of caution and assume it is not thread-safe, and externally synchronize the instance. The fact that no bug has manifested yet does not imply the bug is absent.
Writting to socket is not an atomic operation.
Is better to use a syncrhonized method to writting
Update
https://stackoverflow.com/a/1457347/5065312
All versions of Unix and Windows attempt to keep the write atomic, but apparently very few provide a guarantee.
And if you are using a Realtime Kernel the writes are not atomic.
Update 2:
IEEE Std 1003.1-2017 If the number bytes written to socket is not specified or if the number of bytes written to socket is more than {PIPE_BUF}, then, it does not guarantee that this writting is atomic.
For more information see: man 7 pipe
PostData: It is bad practice to write concurrently without controlling the flow. 99% can work because 99% of the time the socket output will be free
You will have to synchronize in the BufferedWriter when writing from any thread. Even then you are going to have massive problems at the receiving end understanding the stream, unless your protocol consists merely of lines.
Here is the answer of your question: How to get string between two characters using regular expression?
Use this:
$input = "hi my name [is] Mary [Poppins]";
$arr = explode(' ', $input);
$from = "[";
$to = "]";
function getStringBetween($input, $from, $to) {
$sub = substr($input, strpos($input, $from) + strlen($from), strlen($input));
return substr($sub, 0, strpos($sub, $to));
}
foreach ($arr as $data) {
echo getStringBetween($data, $from, $to) . " "; // is Poppins
}

DataOutputStream.writeBytes adds zero-bytes

I have a small TCP server program and a corresponding client, and they communicate via ServerSocket and Socket classes and DataInputStream/DataOutputStream. And I have a problem with sending Strings to the server.
connection = new Socket("localhost", 2233);
outStream = new DataOutputStream(connection.getOutputStream());
outStream.writeBytes(fileName);
fileName is, at this point in time, a hard-coded String with the value "listener.jardesc". The server reads the string with the following code:
inStream = new DataInputStream(connection.getInputStream());
String fileName = inStream.readLine();
The string is received properly, but three zero-value bytes have been added to the end. Why is that and how can I stop it from happening? (I could, of course, trim the received string or somehow else stop this problem from mattering, but I'd rather prevent the problem completely)
I'm just going to throw this out there. You're using the readLine() method which has been deprecated in Java 5, 6 & 7. The API docs state quite clearly that this method "does not properly convert bytes to characters". I would read it as bytes or use a Buffered Reader.
http://docs.oracle.com/javase/1.5.0/docs/api/java/io/DataInputStream.html#readLine%28%29
writeBytes() does not add extra bytes.
The code you've written is invalid, as you aren't writing a newline. Therefore it doesn't work, and blocks forever in readLine().
In trying to debug this you appear to have read the bytes some other way, probably with read(); and to have ignored the return value returned by read, and to have concluded that read() filled the buffer you provided, when it didn't, leaving three bytes in their initial state, which is zero.

Handling IOExceptions from the Google Protocol Buffer library

I have some code that tries to read in a Google Protocol Buffer message from a socket in Java. However, the mergeDelimitedFrom() method can throw an IOException if it reads in invalid data or if the socket connection is reset (and probably other reasons). If the connection is reset I would like to exit out of the loop, but if it is just a invalid message I would like to continue running. One thought is to just have some sort of exception counter and exit after X consecutive failures, but I was hoping to be able to figure out what type of error occurs instead of being in the dark.
This is basically the code I have:
while (m_Running)
{
SomeMessage message = null;
try
{
final Builder builder = SomeMessage.newBuilder();
if (builder.mergeDelimitedFrom(m_InputStream))
{
message = builder.build();
}
else
{
// Google protocol buffers doesn't document it very well
// but if mergeDelimietedFrom returns false then it has
// reached the end of the input stream. For a socket, no
// more data will be coming so exit from the thread
m_Running = false;
}
}
catch (final IOException e)
{
// what should really be done here ???
}
}
Just don't do it. If you are reading protocol buffer objects directly off a socket, then you are effectively defining your own application protocol. It's harder than you might think to do it right - there is a good general description of some of the problems at On the Design of Application Protocols. It's important to understand framing - determining where one message ends and another begins.
Which leads us to some advice from the inventors of protobuf at https://developers.google.com/protocol-buffers/docs/techniques. The key piece of advice is this:
If you want to write multiple messages to a single file or stream, it is up to you to keep track of where one message ends and the next begins.
I recommend that you decide on a framing protocol to divide the stream into messages, then write some custom socket code to handle the work or reading bytes of the sockets, dividing them into byte arrays where each byte array is known to contain exactly one message, then finally use protobuf to deserialize each message-byte-array into an object. Guaranteed no IOException protobuf deserialization.
You'll still have to deal with IOExceptions but it will be at a lower level where you are just reading byte arrays and you'll know exactly how much data has been deserialized when the error occurs.
Also consider using something like netty to help with the socket code.

Categories

Resources