Do i have to synchronize socket.send? - java

I have 2 classes where I have one to send commands to a socket, another which receives (and sometimes answers commands) .
Do I have to synchronize this? Or is this not necessary?
Both classes run in their own threads with the socket object passed down to each of them as argument upon thread.start();
Is this the proper way to do it or could I do something more efficient?
Would this have chances of causing errors?
The sending part:
public void run(){
send_chatline("roomf");
int vvv = 0;
while (this.socket.isConnected()){
try{
Thread.sleep(10000);
vvv++;
Thread.sleep(10000);
send_chatline("alive");
Thread.sleep(10000);
if (vvv == 1) {
this.socket.flush();
this.socket.send("T,-1," + this.playerid * 3);
this.socket.flush();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
But remember! The recieveFromSock class also writes sometimes when specific commands appear.
The only function of sendTosock is to keep the connection alive (being able to remain online).

The only guarantee you have is that a byte sent, is sent once, and that a byte read is read once. Others may say that the synchronization is taken care of by the runtime-library, or the underlying operating system. Any such statement is runtime-implementation dependent and/or operating system dependent (and should in my opinion be disregarded from).
So, if you have one thread reading from the socket, and one thread writing to the socket, you should be fine without synchronization.
If more than one thread may write to the socket, you should synchronize their actions to make sure the output sent from the two threads doesn't get interleaved.
Same applies if two threads read from the socket. You should synchronize the reads to make sure that data read by one thread doesn't have "gaps" due to reads of another thread.
Similar question, same conclusion:
in what way is java.net.Socket threadsafe?

Do I have to synchronize this?
No. SocketImpl has its own internal synchronization. You won't be surprised to learn that sending isn't synchronized but receiving is.

You don't need to synchronize, as the synchronization is done on the socket. The question is: are the two classes/threads communicating through sockets living in the same JVM? If so, there are several more efficient options, the most simple being having a BlockingQueue where the sender class adds its commands and the receiver takes them.

I was curious too for the nio classes and it IS synchronized(for nio only). Just look at the write method here in the sun JVM code
http://www.docjar.com/html/api/sun/nio/ch/SocketChannelImpl.java.html
Checking the old i/o socket code however shows no synchronization though there is an acquireFD and releaseFD...but no sycnhronization there...that appears to prevent a close until all writes on all threads are done(it is like they assume writes from multiple threads are okay in every OS...but I don't know if that is true OR they synchronize in the JVM native code so the developer knows they can do that)....we would need a JVM developer to tell us if there is a synch block in the windows JVM, linux JVM and mac JVM, etc. etc....
private void socketWrite(byte b[], int off, int len) throws IOException {
if (len <= 0 || off < 0 || off + len > b.length) {
if (len == 0) {
return;
}
throw new ArrayIndexOutOfBoundsException();
}
FileDescriptor fd = impl.acquireFD();
try {
socketWrite0(fd, b, off, len);
} catch (SocketException se) {
if (se instanceof sun.net.ConnectionResetException) {
impl.setConnectionResetPending();
se = new SocketException("Connection reset");
}
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
} else {
throw se;
}
} finally {
impl.releaseFD();
}
}

Related

Java - synchronized lock hangs tablet (Bluetooth LE Android)

I have a Unity3D app with a Java plugin I've written in Android Studio for accessing a BluetoothLE server over on my Raspberry Pi 3 from my Android device, as well as an Objective-C plugin for XCode on the IOS side for CoreBluetooth. On the plugin side my Objective-C code works perfectly on IOS, but my Java crashes and burns on Android, and freezes the whole tablet, I'm not too surprised. Also notably, it's already taken me about 3x longer so far to code plugin support in Java. Maybe it's time to have a fresh set of eyes looking at it.
The difference is that CoreBluetooth's functions on IOS seem to read a GATT characteristic synchronously while Java requires asynchronous callbacks that don't seem to be working for me. It causes Unity and the entire tablet to hang until reboot.
Here is the part causing problems (it's two parts).
This first part is where I have Unity telling BluetoothLE to go start reading the pins (GetPins). I wanted it to basically act synchronously and wait until it's retrieved data so it can return a string like I've coded in the IOS version so I have it do a synchronized lock.
Basically Java is imposing an asynchronous coding model that's unnecessary on the IOS side (in fact, I'm not so sure there's an asynchronous way to code GATT characteristic reading on IOS CoreBluetooth, but I could be wrong), that would cause me to have to rewrite my entire plugin structure from Unity to support what Java's doing, which is going to be a lot more fiddly in the end and may break other things in the process.
public String GetPins() {
String returnValue = "";
if (mConnected) {
try {
if (getPinsCharacteristic == null) {
List<BluetoothGattService> services = mGatt.getServices();
if (mServiceRead == null) {
mGatt.discoverServices();
mServiceWrite = mGatt.getService(ServiceWriteUUID);
mServiceRead = mGatt.getService(ServiceReadUUID);
mServiceNotify = mGatt.getService(ServiceNotifyUUID);
}
getPinsCharacteristic = mServiceRead.getCharacteristic(PinsCharacteristic);
}
} catch(Exception ex) {
Log.i("MERRRRRP",String.format("Exception: (%s)",ex.toString()));
}
Log.i("MERRRRRP", "Reading Pins");
if (getPinsCharacteristic != null) {
try {
boolean success = mGatt.readCharacteristic(getPinsCharacteristic);
isReadingPins = true;
while(isReadingPins) {
synchronized (readLockPins) {
try {
readLockPins.wait(1);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
}
returnValue = new String(getPinsCharacteristic.getValue(), "UTF-8");
}
catch(Exception ex) {
returnValue = ex.toString();
}
}
}
return returnValue;
}
Now this is the part onCharacteristicRead where it's actually getting the result back, and should be unlocking the synchronized lock and I should get the value back. Instead the whole tablet is freezing.
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
if (characteristic.equals(getPinsCharacteristic)) {
synchronized (readLockPins) {
isReadingPins = false;
}
}
}
}
Your first block of code acquiring lock in a loop and holding it for one second. You assume that your second block of code will execute and acquire the lock between those iterations in first block.
That assumption is wrong. The locks are not fair. If thread A is acquiring and releasing a lock in the loop, and thread B is trying to acquire that same lock, there is not guarantee, that thread B gets it in reasonable time (or maybe never).
The second potential problem (I cannot determine from the code you just posted) is that the variable isReadingPins in while(isReadingPins) MUST be volatile.
Variables not marked volatile do not trigger memory barrier operation, which results in the scenario where writing to the variable in one thread is not visible in another thread.
In your case, isReadingPins = false; in second code block will probably not be visible to the thread running the first code block, because value of the variable will in cache local to the CPU core running that code block, which will always be true, because the write to false is local to another CPU core and CPU core caches will not be synchronized due to absence of memory barrier. This is why the variable must be volatile.
In the end, this is pretty clumsy way of doing this. I don't know Android API, but in regular Java this would be solved using a promise/future or at least a simple Latch.
edit And another thing... if your read function fails, or returns something that is not GATT_SUCCESS, then isReadingPins is never set to false and your application just freezes. This is bad design.

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.

Bluetooth InputStream.read() doesn't return Data and Blocks forever

I've got some problems with Android Bluetooth stuff.
When I call
bytes = mmInStream.read(buffer);
It usually works as it should.
On the Cat B15 smartphone however, the read method sometimes blocks forever, even though the connection is still running and data should be arriving.
I have temporarily solved the problem by this code:
while (true) {
int available = 0;
try {
available = mInStream.available();
} catch (IOException e) {}
if (available > 0) {
try {
bytes = mInStream.read(buffer);
ioExceptionsCounter = 0;
// [send the obtained bytes to the UI activity]
// ...............
} catch (IOException e) {
++ioExceptionsCounter;
if (ioExceptionsCounter >= 4) {
break;
}
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
I dont think that the ioExceptionsCounter is really necessary but there was some complaints that it sometimes disconnects without reason so I thought one IOException might not be enough to close the connection.
What I really don't like about this is that it uses polling. It does work now on the Cat phone but it doesn't make me happy that all the other devices now execute this ugly code.
Do you have any ideas why this could be? Is this just a bug of the phone? By the way it runs ICS but it is definitely device specific.
I'm inclined to think that you are encountering a hardware-specific bug.
The various InputStream.read() methods are documented to block until at least one byte is read, or the end of the stream is detected, or an error occurs. If the read() sometimes blocks forever for you in the event that no bytes are available when it is first invoked, then that's definitely a bug outside your own code.
Also, it's highly questionable to ignore any number of IOExceptions, either from available() or from read(). After the stream throws an exception you cannot be confident of the integrity of anything you afterward might manage to read from it. I would normally expect such attempts at further reading also to throw IOExceptions. If you are getting spurious IOExceptions on the Cat B15, such that simply retrying your read() successfully obtains the correct data, then that is also a bug (maybe another facet of the same one).

java Process' inputStream stuck

Here's my scenario:
process A spawns child process B and spins threads to drain B's outputs.
process B spawns daemon process C and drains its outputs, too.
process B finishes, daemon process still lives.
process A finds out that process B exited via process.waitFor(). However, it's stuck on reading the input streams of process B. It's because B has started a daemon. The input stream receives EOF only when the process C exits.
This only happens on Windows. I'm using the ProcessBuilder. Here're the solutions I came up with and I'd like to hear your feedback as none of the solutions I really like:
I can use jna to spawn the daemon process C. This way I can create a process that is 'detached enough' and process A is not stuck on draining the streams from B. It works but I'm not very keen on that solution because it means some native code (and lots of that since I'm keen on consuming the inputs). Some inspiration how to do it via JNA is here: http://yajsw.sourceforge.net (however it contains way more stuff than mere process starting).
Run on jre7. Jdk7 brings some new goodies to the ProcessBuilder, e.g. inheritIO() stuff that also solves my problem. Apparently, when inheritIO() is turned on, I can simply close all streams in the daemon process C (which I do anyway because it'a daemon) and that solves the problem. However, I need to run on jre5+
Close the System.out and System.err in process B before spawning the daemon process C. Again, it solves the problem but I really need those streams to work in process B as I write useful stuff to them. No good. I hoped I could take advantage of this characteristic by placing some kind of a bootstrap process between B & C but that didn't solve the problem.
I don't have that problem on linux so could I only run on linux? No, I can't.
Made the process A drain the outputs of process B in a non-blocking way. This somewhat works but it's not convenient. E.g. inputStream.read() is not interruptible. I could use inputStream.available() but it doesn't distinguish between EOF and zero-bytes-available. So the solution is only good if process A is never interested in B's output EOF. Also, this solution seems to be more CPU intensive and generally... feels awkward and not really bullet proof.
Run process C in a --dry-run mode where it just checks if it can be started. It tries to start, sends welcome message and exits. It's no longer long-running so it will not block reads. Process B can gain enough confidence that C can be started and we can use relatively simple JNA code to spawn detached process without consuming its outputs (it's the consuming of outputs makes the JNA-related code messy and heavyweight). The only problem is that we no longer consumer process' C outputs but it can be solved by making C write to a well known file that process B can consume. This solution is more like a big and ugly workaround but kind of workable for us. Anyways, we are trying the solution 1) at the moment.
I would really appreciate any hints!
I just encountered the same problem. I think I have a workaround to the problem. In process A, I have the following code fragment after Process.waitFor(), where outT and errT are the threads to read process B's stdout and stderr, respectively:
try {
outT.join(1000);
if (outT.isAlive()) {
errmsg("stdout reader still alive, interrupting", null);
outT.interrupt();
}
} catch (Exception e) {
errmsg("Exception caught from out stream reader: "+e, e);
}
try {
errT.join(1000);
if (errT.isAlive()) {
errmsg("stderr reader still alive, interrupting", null);
errT.interrupt();
}
} catch (Exception e) {
errmsg("Exception caught from err stream reader: "+e, e);
}
p.destroy();
Not sure if p.destroy() is needed, but I have been trying all kinds of combinations to deal with the problem.
Anyway, in the run() method of the outT/errT threads, I have the following, where the 'pipe' variable is a Writer instance I am capturing stdout/stderr of the sub-process to. The 'in' variable is the stdout, or stderr, stream obtained from Process:
try {
r = new BufferedReader(new InputStreamReader(in, enc));
String line;
while (true) {
if (Thread.currentThread().isInterrupted()) {
errmsg("Text stream reader interrupted", null);
break;
}
if (r.ready()) {
line = r.readLine();
if (line == null) {
break;
}
pipe.write(line);
pipe.write(SystemUtil.EOL);
if (autoFlush) {
pipe.flush();
}
}
}
pipe.flush();
} catch (Throwable t) {
errmsg("Exception caught: "+t, t);
try { pipe.flush(); } catch (Exception noop) {}
} finally {
IOUtil.closeQuietly(in);
IOUtil.closeQuietly(r);
}
It seems that I never get an EOF indication from any sub-process, even after the sub-process terminates, hence, all the chicanery above to prevent stale threads and blocking.

What is the correct way to stop a thread waiting for network activity?

This question has no doubt been asked in various forms in the past, but not so much for a specific scenario.
What is the most correct way to stop a Thread that is blocking while waiting to receive a network message over UDP.
For example, say I have the following Thread:
public class ClientDiscoveryEngine extends Thread {
private final int PORT;
public ClientDiscoveryEngine(final int portNumber) {
PORT = portNumber;
}
#Override
public void run() {
try {
socket = new DatagramSocket(RECEIVE_PORT);
while (true) {
final byte[] data = new byte[256];
final DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
}
} catch (SocketException e) {
// do stuff 1
} catch (IOException e) {
// do stuff 2
}
}
}
Now, would the more correct way be using the interrupt() method? For example adding the following method:
#Override
public void interrupt() {
super.interrupt();
// flip some state?
}
My only concern is, is socket.receive() not a non-interruptable blocking method? The one way that I have thought of would be to implement the interrupt method as above, in that method call socket.close() and then cater for it in the run method in the catch for the SocketException. Or maybe instead of while(true) use some state that gets flipped in the interrupt method. Is this the best way? Or is there a more elegant way?
Thanks
The receive method doesn't seem to be interruptible. You could close the socket: the javadoc says:
Any thread currently blocked in receive(java.net.DatagramPacket) upon
this socket will throw a SocketException
You could also use setSoTimeout to make the receive method block only for a small amount of time. After the method has returned, your thread can check if it has been interrupted, and retry to receive again for this small amount of time.
Read this answer Interrupting a thread that waits on a blocking action?
To stop a thread, you should not user neither interrupt nor stop in java. The best way, as you suggested by the end of your question, is to have the loop inside the main method controlled by a flag that you can rise as needed.
Here is an old link about this :
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Other ways of stopping a thread are deprecated and don't provide as much control as this one. Also, this may have changed a bit with executor services, I didn't have time to learn much about it yet.
Also, if you want to avoid your thread to be blocked in some IO state, waiting for a socket, you should give your socket a connection and reading time out (method setSoTimeout).
Regards,
Stéphane
This is one of the easier ones. If it's blocked on a UDP socket, send the socket a UDP message that instructs the receiving thread to 'stop'.
Rgds,
Martin

Categories

Resources