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.
Related
I know that InputStreams are for reading, and OutputStreams are for writing... but if I have an application that passes all data from an InputStream to the remote side and pushes all received data from that remote side to the OutputStream and I need to send dynamic data to that remote side... how would I enter it into the InputStream? I can do this easily in the Java console since anything entered in is put into System.in and sent to that remote side, and anything coming back is processed through System.out, but obviously I cannot use a Java console in production. How would I emulate this functionality e.g. create a button that sends "command X\r" as if it were typed into the java console?
Note: For background, I'm using JSch to SSH into a Cisco ASA. Where I have set Channel.setInputStream(System.in) and Channel.setOutputStream(System.out) to communicate through console successfully.
I am not familiar with JSch, and I suspect you have this backwards. First, according to their example, you should actually be executing commands with Channel.setCommand(). Then you can use Channel.getInputStream() to obtain a stream that you can read the remote response from.
That aside, a cursory glance at the documentation seems to suggest that you should use the channel's existing streams and read to / write from them, e.g.:
OutputStream out = Channel.getOutputStream();
String str = "command X\r";
out.write(str.getBytes("us-ascii"));
This would make more sense and is much easier to deal with on your end.
However, as to the general question regarding InputStreams: You can use any InputStream as a source for data. It just so happens that System.in is one that comes from standard input (which is essentially a file).
If you want to use data constructed on the fly, you could use a ByteArrayInputStream, e.g.:
String str = "command X\r";
InputStream in = new ByteArrayInputStream(str.getBytes("us-ascii"));
// do stuff with in
You can use any character encoding you want if us-ascii is not appropriate.
But, again, I suspect you are doing this slightly backwards.
I am trying to testing FTP by using SocketChannel, but it is not really in my expectation. I knew that I need to setup a selector algorithm which select the OP_CONNECT, OP_READ key to perform the connect and read function, everything is working fine but why the incoming data is not completely read? On the other hand, if I'm debugging the program, it can be read correctly as I doing it very slow. I thought it is synchronizing issue, so I try to submit only 1 key(even tried hard coded the method step by step, but the issue still existed.
Has anyone met this issue? How can I ensure that the full incoming data is ready to read instead of partial data only, sometimes no data (=.=")
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.
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.
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.