Java - Client recieving blank messages from Server, but only over network - java

I was unsure whether this issue is to do with the network, but I'm trying to get a simple server to send messages to multiple clients. It works fine when testing on my own computer, but over the network to a different computer has issues.
The client connects to the server fine, the first message sent to the client SHOULD be 'Server : Hello, World!', but a blank string comes through. Then the second string is always read as it should be, and all the rest usually come out as blank strings. The server sends info via a PrintStream, using autoflush.
Below is the part of the Client program which reads input. I believe if anything, there is an issue here, but I'm not sure what since I'm a little new to sockets and networking things. The server sends a line of text each 500 milliseconds, counting up to each client. I've tried changing this number to something higher but the client still doesn't receive the correct messages. The client should receive the messages and print them to the screen, replying with the replies seen below at 5,10,15 and 20.
try {
socket.setSoTimeout(10);
String line;
while((line = input.readLine())!=null){
if (!line.equals("")){
// Replies
if (output != null) {
if (line.endsWith(" 20")){
output.println("Reached 20!");
}else if (line.endsWith(" 15")){
output.println("Reached 15!");
}else if (line.endsWith(" 10")){
output.println("Reached 10!");
}else if (line.endsWith(" 5")){
output.println("Reached 5!");
}
}
messages.add(line);
if (messages.size() >= 8){
messages.remove(0);
}
}else{
messages.add("EMPTY STRING!!");
if (messages.size() >= 8){
messages.remove(0);
}
}
}
} catch (SocketTimeoutException e){
// Timed out
} catch (Exception e) {
System.err.println("Connection lost");
break;
}
(Quick Edit: Should probably mention this is in a while loop inside the run method since I implemented Runnable on my class.)
When using input.readLine(), should I be checking something before to make sure it doesn't come out as just empty strings? Is it because of the timeout I have put on it?
Thanks in advance, and I should also mention I'm new to stackoverflow, If I'm doing anything wrong please say! :)

Okay, Well. Turns out it was to do with the timeout being too small. I put it up to a whole second and now it prints out fine. Thanks anyway people :)

Related

Java Server - Sending packets out incorrectly?

Currently have a TCP server built in Java and I'm sending messages/packets out to clients using their socket's OutputStream:
// Send all player's information to everyone else
outerPlayerIter = players.iterator();
while(outerPlayerIter.hasNext()) {
Player outerPlayer = outerPlayerIter.next();
Iterator<Player> innerPlayerIter = players.iterator();
while(innerPlayerIter.hasNext()) {
Player innerPlayer = innerPlayerIter.next();
boolean isYou = false;
if(innerPlayer.equals(outerPlayer)) isYou = true;
// Send innerPlayer's info to outerPlayer
Thread.sleep(100);
dataBuffer.clearBuffer();
dataBuffer.writeByte(Msgs.mm_toclient.MES_SENDPLAYERINFO);
dataBuffer.writeBool(isYou);
dataBuffer.writeBool(innerPlayer.getIsHost());
dataBuffer.writeString(innerPlayer.getName());
dataBuffer.writeString(innerPlayer.getPublicIP().getHostAddress());
dataBuffer.writeShort((short)innerPlayer.getUdpPort());
outerPlayer.getSocket().getOutputStream().write(dataBuffer.getByteArray());
outerPlayer.getSocket().getOutputStream().flush();
}
}
However, sometimes the clients don't appear to receive all the messages. I can't send multiple messages at the exact same time over one socket.
One way to temporarily fix this was to sleep before I send another packet out. But I'm not sure why this is needed.
Am I doing something wrong in regards to how I'm sending/writing the packets out to be sent? What can be fixed to allow multiple packets to be received correctly at once without sleeping?
It might be due to the fact that the client closes the socket way too fast before the communication should actually finished. Could you please try to bump up the thread.sleep value or, on the client side, if you use any kind of timing, try to bump up that one as well.

What happens to data received by a socket in case of timeout exception during readShort()?

I'm developing a client (Java)/server(C++) application using TCP sockets.
The protocol I used is composed of Messages beginning by 2 bytes defining the type of what will be the content of the Message.
So basically, the receiving thread waits for data to be received in a loop. But I want to use a timeout with the socket to be notified that the other host takes too long to send data.
receivingSocket.setSoTimeout(durationInMilliseconds);
DataInputStream in = new DataInputStream(receivingSocket.getInputStream());
boolean success = false;
short value = 0;
do {
try {
value = in.readShort();// will throw a SocketTimeoutException in case of timeout, without 2 bytes available from the socket
success = true;
} catch (SocketTimeoutException e) {
/// do something if it happens to often. Otherwise go on with the loop
}
} catch (IOException e) {
/// abort connection in case of other problem
}
} while (!success)
Now, what happens if the receiving thread calls in.readShort() at a point where the socket has got only one byte available in its buffer ? Does this byte remain on the socket's stack ? Or is it lost ? In the first case, I could read it next time I call in.readShort(), otherwise it seems lost for good...
readShort() here is an example, my question stands also for readInt(), ...
Thanks for your help,
It isn't specified. I believe the way the implementation works is that the half data is lost, but in any case there's nothing written that says anything else, so you just have to assume the worst.
However in practice this is very unlikely to happen, provided you observe common sense at the sender.

While loop not continuing - socket

Okay, so I'm creating a rather simple java application, which will eventually turn into an online 2-player texas hold'em game. Right now, I'm trying to send some simple messages over network to make sure the basic functionality is working. I am however stuck.
I've got two methods in a class. One for the serverside (or really a hybrid between a client and a server), and one for the clientside. They connect together fine. As I made this, I noticed that when I connected, they both spammed their default messages (right now being "CLIENT: Started" and "SERVER: Started" back and forth to eachother. I figured this was because the string containing that information was never emptied, and so they never knew when to stop transmitting it. I then made sure that after sending the message, that variable was nulled, and a check was made to see if it was null before sending.
Here's where it went wrong though! After doing that, they won't send more than one message at all. They send their respective welcome messages, but anything I try to transmit after that is ignored. It's almost like if the while-loop for the server/client stops.
So, I have two public variable declared in the class. These contain any message the server or client wishes to send.
public static String serverCommand = null;
public static String clientCommand = null;
They are null by default, but changed during runtime in the GUI-part.
The server loop looks like this:
while(true)
{
if((receive = receiveStream.readLine()) != null)
{
System.out.println(receive);
}
if(serverCommand != null)
{
printer.println(serverCommand);
printer.flush();
Network.serverCommand = null;
}
}
And the client while loop like this:
while(true)
{
if(Network.clientCommand != null)
{
printer.println(clientCommand);
printer.flush();
Network.clientCommand = null;
}
if((receive = receiveStream.readLine()) != null)
{
System.out.println(receive);
}
}
However, as mentioned - after Network.clientCommand is set to null the first time around, it never again sends any messages, even though Network.clientCommand changes due to user input during runtime.
I'll post two links to the complete sourcecode of the client/server-part of this below, as they're a bit too big to paste here.
LINK: http://hastebin.com/oqotirufic.java
Does anyone here have any idea what's happening, and how should I think when trying to fix/get around it? I'll add that my experience with both Java and network programming is very limited.
EDIT
I'll add the part of the GUI which acccesses/changes the variables.
http://hastebin.com/upadayuwug.java
Of course after Network.clientCommand is null, nothing more is sent — that's what you told it to do:
if((receive = receiveStream.readLine()) != null)
{
System.out.println(receive);
}
According to the JavaDoc, readLine() returns
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached
Not "null if there's a pause in transmission". If it hasn't yet seen a full line, or the end of the stream (socket disconnection), well, then it's not done yet. It waits until it gets the full line of input before it goes to the next line of your code.
But how do you know if you should wait for a message to come in, or send out the next one? You can't. You can't depend on when or if anything will arrive from the other side.
What happens when both sides have nothing to send? They both start waiting to receive. What happens when one side gets something new to send? Well, once it receives something, it'll send it. But that never happens!
What you can do, is call readLine() in a separate thread. See the JavaDocs for Thread and the Java Tutorial Lesson "Concurrency". And if you're using Swing for your GUI, also see the Java Tutorial Lesson "Concurrency in Swing".

Socket never stop searching for SocketServer

Ok so my question is really simple as I have it I pretty much have a server and a client program, however I don't want my server to have to be on for client to run, so I want to have it so the client never stops searching for server and all I have to do is turn server on, does anyone know how I'd do that? thanks
Put it in a while loop. Keep in mind that this will stall your program until it connects, so you should probably do this on a separate thread.
boolean done = false;
while (!done) {
try {
// Socket initialization code
} catch (IOException e) {
if (!e.getMessage().equals(/* Error code for unable to find server */) {
done = true;
}
}

Issues receiving in RXTX

I've been using RXTX for about a year now, without too many problems. I just started a new program to interact with a new piece of hardware, so I reused the connect() method I've used on my other projects, but I have a weird problem I've never seen before.
The Problem
The device works fine, because when I connect with HyperTerminal, I send things and receive what I expect, and Serial Port Monitor(SPM) reflects this.
However, when I run the simple HyperTerminal-clone I wrote to diagnose the problem I'm having with my main app, bytes are sent, according to SPM, but nothing is received, and my SerialPortEventListener never fires. Even when I check for available data in the main loop, reader.ready() returns false. If I ignore this check, then I get an exception, details below.
Relevant section of connect() method
// Configure and open port
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
.open(owner,1000)
port.setSerialPortParams(baud, databits, stopbits, parity);
port.setFlowControlMode(fc_mode);
final BufferedReader br = new BufferedReader(
new InputStreamReader(
port.getInputStream(),
"US-ASCII"));
// Add listener to print received characters to screen
port.addEventListener(new SerialPortEventListener(){
public void serialEvent(SerialPortEvent ev) {
try {
System.out.println("Received: "+br.readLine());
} catch (IOException e) { e.printStackTrace(); }
}
});
port.notifyOnDataAvailable();
Exception
java.io.IOException: Underlying input stream returned zero bytes
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:268)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.read(BufferedReader.java:157)
at <my code>
The big question (again)
I think I've eliminated all possible hardware problems, so what could be wrong with my code, or the RXTX library?
Edit: something interesting
When I open HyperTerminal after sending a bunch of commands from java that should have gotten responses, all of the responses appear immediately, as if they had been put in the buffer somewhere, but unavailable.
Edit 2: Tried something new, same results
I ran the code example found here, with the same results. No data came in, but when I switched to a new program, it came all at once.
Edit 3
The hardware is fine, and even a different computer has the same problem. I am not using any sort of USB adapter.
I've started using PortMon, too, and it's giving me some interesting results. HyperTerminal and RXTX are not using the same settings, and RXTX always polls the port, unlike HyperTerminal, but I still can't see what settings would affect this. As soon as I can isolate the configuration from the constant polling, I'll post my PortMon logs.
Edit 4
Is it possible that some sort of Windows update in the last 3 months could have caused this? It has screwed up one of my MATLAB mex-based programs once.
Edit 5
I've also noticed some things that are different between HyperTerminal, RXTX, and a separate program I found that communicates with the device (but doesn't do what I want, which is why I'm rolling my own program)
HyperTerminal - set to no flow control, but Serial Port Monitor's RTS and DTR indicators are green
Other program - not sure what settings it thinks it's using, but only SPM's RTS indicator is green
RXTX - no matter what flow control I set, only SPM's CTS and DTR indicators are on.
From Serial Port Monitor's help files (paraphrased):
the indicators display the state of the serial control lines
RTS - Request To Send
CTS - Clear To Send
DTR - Data Terminal Ready
OK, sorry it's taken me so long to come back to this question. Here's how I got things working.
Note: This method will NOT work for everyone, please read below before copy/pasting into your own code
public void connect(CommPortIdentifier portId) throws Failure {
if (portId == null)
throw new Failure("No port set");
try { port = (SerialPort) portId.open(getClass().getName(), 10000); }
catch (PortInUseException e) {
throw new Failure("Port in use by " + e.currentOwner,e); }
try {
port.setSerialPortParams(9600, SerialPort.DATABITS_8,
SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
port.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN
| SerialPort.FLOWCONTROL_RTSCTS_OUT);
} catch (UnsupportedCommOperationException e) { throw new Failure(e); }
port.setRTS(true);
// More setup
}
So, in my case, the problem was that my particular device requires RTS flow control. Other devices may require different things (CTS, XON/XOFF), so check that device's manual. By default, RXTX disables all flow control mechanisms (unlike Hypertrm or other programs). Enabling each one is a two-step process.
Once you have a SerialPort object, call the setFlowControlMode() method, and bitwise-OR ('|') the necessary SerialPort.FLOWCONTROL_ constants
Set the appropriate flow control to true or false (like I did with port.setRTS(true))
For the others with similar problems, if this doesn't work, I suggest
Using a serial port monitoring program like Serial Port Monitor and/or PortMon (both Windows) to see what is actually going on.
Emailing the RXTX developers at rxtx#qbang.org (they are very helpful)
There is a simpler solution to this problem. This is what I did:
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line;
while (keepRunning) {
try {
while ((br.ready()) && (line = br.readLine()) != null) {
....
}
If you check that the buffer "is ready" before you read it there should be no problem.
Ok, I do realize this thread is extremely old, but none of these solutions worked for me. I had the same problem and I tried everything to fix it, to no avail. Then I did some research on what causes the problem, and, when not dealing with Serial Communication, it happens at the end of a file. So, I figured I needed to add an ending to whatever is being received by the Java Application, specifically, a line return (\n). And sure enough, it fixed the problem for me! Hopefully this helps someone new, as I'm not expecting this to help anyone already on this thread...
(might be too simple, but might as well start somewhere...)
Is the port in use? Rather than:
port = (SerialPort) CommPortIdentifier.getPortIdentifier(name)
.open(owner,1000)
what about:
CommPortIdentifier portIdentifier;
try {
portIdentifier = CommPortIdentifier.getPortIdentifier(name);
} catch (NoSuchPortException nspe) {
// handle?
}
if (portIdentifier.isCurrentlyOwned()) {
// handle?
}
port = portIdentifier.open(owner, 1000);
if (!(port instanceof SerialPort)) {
// handle?
}
Are you swallowing any exceptions?
I tried RXTX a few months ago and ran into similar problems. I suggest two things:
Create a virtual comport using com0com. Enable trace logging. Compare the logs for when you use Hyperterminal versus when you run your own program. The difference will highlight what you are doing wrong.
In my humble opinion, RXTX's design is flawed and its implementation is quite buggy (take a look at its source-code, what a mess!). I've published an alternative library at http://kenai.com/projects/jperipheral with the following caveats: It's Windows-only and there are no pre-built binaries. Both of these will change in the near future. If you are interested in trying it out send me an email using http://desktopbeautifier.com/Main/contactus and I'll send you a pre-built version.
If anyone is still getting java.io.IOException: Underlying input stream returned zero bytes after you've read your characters using br.readline() for RXTX (even when you are checking first to see if br.readline() == null), just do this simple fix with a try/catch:
String line;
while (true){
try{
line = br.readLine();
}catch(IOException e){
System.out.println("No more characters received");
break;
}
//Print the line read
if (line.length() != 0)
System.out.println(line);
}
I've done some searching and it appears that this is the best/easiest way to get around this problem.
EDIT : I take that back. I tried this and still ended up having some problems. I'd recommend working with the raw InputStream directly, and implementing your own read/readLine method using InputStream.read(). That worked for me.

Categories

Resources