'Best way to share a serialized object among several nearby Android devices in java
I am a long-time programmer, but fairly new to Android tablet programming and java. I am presently attempting to display data on multiple tablets from a device with a limited UDP capability. This UDP device can only talk to one tablet at a time, and I have a tablet successfully communicating with it now, but my difficulty is trying to share this data with the other tablets. All of these tablets are running the same app, with a setting to tell which tablet handles the communication with the UDP device. The selected tablet also runs a TCP server, while the others run a matching TCP client. All that I need from this TCP communication is for the server to send the clients a custom serialized object, which contains all of the data that the tablets need, at a periodic rate of once every 100ms.
After a lot of google searches, stackoverflow searches, and experimentation, I am now running the following code. The server tablet calls StartTxServer once to start the process, while the rest of the tablets call RunRxClient periodically every 100ms.
private void StartTxServer() throws IOException
CustomSerial localdata;
ServerSocket server = null;
try {
server = new ServerSocket(TCP_Port) // TCP_Port is a constant int telling the port number
while(Server_Active) { // ServerActive is a boolean
Socket socket = server.accept();
InputStream streamin = socket.getInputStream();
ObjectOutputStream streamout = new ObjectOutputStream(socket.getOutputStream());
byte[] buffer = new byte[1024];
int bytes;
bytes = streamin.read(buffer);
// The following line creates a current copy of my custom serializable object.
localdata = customdata.ConvertToSerial();
streamout.writeObject(localdata);
streamin.close();
streamout.close();
socket.close();
}
} catch (IOException e) {
Log.e("TCP_Server", "Server ERROR: ".concat(e.getMessage()));
e.printStackTrace();
} finally {
server.close();
}
if(Server_Active) {
Log.i("TCP_Server", "Triggering a function restart");
final Runnable restartserver = new Runnable() {
@Override
public void run() {
try {
StartTxServer();
} catch (IOException e) {
e.printStackTrace();
}
}
};
threads.execute(restartserver);
}
}
private void RunRxClient() throws IOException {
CustomSerial localdata;
Socket socket = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
// IP_MasterAddressLocal is a constant IP string, which the server tablet needs to have
// as a static address in order to work with the UDP device.
// TCP_Port is the constant int already referred to in the server function.
socket = new Socket(IP_MasterAddressLocal, TCP_Port);
socket.setSoTimeout(1000);
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
oos.writeObject("R"); // Only one byte for efficiency. Stands for "Request Data".
localdata = (CustomSerial) ois.readObject();
customdata.ConvertFromSerial(localdata); // Loads data into non-serialized object for display.
} catch (IOException | ClassNotFoundException e) {
Log.e("TCP_Client", "ERROR: ".concat(e.getMessage()));
e.printStackTrace();
} finally {
socket.close();
oos.close();
ois.close();
}
}
With this code, the server side seems to run successfully with no errors noted. But when I connect the client tablet to my PC, I see in the Android Studio Logcat that most of the attempts at communication fail. Usually I get an "ECONNRESET" error, though sometimes I see an "EPIPE" error instead. From time to time, one message gets through successfully without setting either error. When that happens, the client tablet's screen updates correctly, proving that my serialization and deserialization routines work properly. But the client tablet's screen is quite "jerky", with inconsistent updates as would be expected with the low number of successful data receptions. As I develop this code, the tablets are right next to each other on a desk, so Wi-Fi connectivity between them should not be an issue. The full text of sample error messages are below.
E/TCP_Server: ERROR: java.net.SocketException: sendto failed: ECONNRESET (Connection reset by peer)
W/System.err: java.net.SocketException: sendto failed: ECONNRESET (Connection reset by peer)
W/System.err: at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:546)
W/System.err: at libcore.io.IoBridge.sendto(IoBridge.java:515)
W/System.err: at java.net.PlainSocketImpl.write(PlainSocketImpl.java:504)
W/System.err: at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:37)
W/System.err: at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:266)
W/System.err: at java.io.DataOutputStream.write(DataOutputStream.java:98)
W/System.err: at java.io.ObjectOutputStream.writeNewString(ObjectOutputStream.java:1429)
W/System.err: at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1637)
W/System.err: at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
W/System.err: at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
W/System.err: at com.ntt.coursetracker.WiFiService.RunRxClient(WiFiService.java:2398)
W/System.err: at com.ntt.coursetracker.WiFiService.StartTx(WiFiService.java:2296)
W/System.err: at com.ntt.coursetracker.WiFiService.access$200(WiFiService.java:48)
W/System.err: at com.ntt.coursetracker.WiFiService$10.run(WiFiService.java:2268)
W/System.err: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: android.system.ErrnoException: sendto failed: ECONNRESET (Connection reset by peer)
W/System.err: at libcore.io.Posix.sendtoBytes(Native Method)
W/System.err: at libcore.io.Posix.sendto(Posix.java:206)
W/System.err: at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278)
W/System.err: at libcore.io.IoBridge.sendto(IoBridge.java:513)
W/System.err: ... 19 more
E/TCP_Server: ERROR: java.net.SocketException: sendto failed: EPIPE (Broken pipe)
W/System.err: java.net.SocketException: sendto failed: EPIPE (Broken pipe)
W/System.err: at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:546)
W/System.err: at libcore.io.IoBridge.sendto(IoBridge.java:515)
W/System.err: at java.net.PlainSocketImpl.write(PlainSocketImpl.java:504)
W/System.err: at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:37)
W/System.err: at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:266)
W/System.err: at java.io.DataOutputStream.write(DataOutputStream.java:98)
W/System.err: at java.io.ObjectOutputStream.writeNewString(ObjectOutputStream.java:1429)
W/System.err: at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1637)
W/System.err: at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
W/System.err: at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
W/System.err: at com.ntt.coursetracker.WiFiService.RunRxClient(WiFiService.java:2398)
W/System.err: at com.ntt.coursetracker.WiFiService.StartTx(WiFiService.java:2296)
W/System.err: at com.ntt.coursetracker.WiFiService.access$200(WiFiService.java:48)
W/System.err: at com.ntt.coursetracker.WiFiService$10.run(WiFiService.java:2268)
W/System.err: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: android.system.ErrnoException: sendto failed: EPIPE (Broken pipe)
W/System.err: at libcore.io.Posix.sendtoBytes(Native Method)
W/System.err: at libcore.io.Posix.sendto(Posix.java:206)
W/System.err: at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278)
W/System.err: at libcore.io.IoBridge.sendto(IoBridge.java:513)
W/System.err: ... 19 more
Is there a simple fix which would get rid of these errors? I have tried re-writing my functions to match the sample code of plenty of other stackoverflow pages, but the errors persist. Alternatively, is there an easier way to do this? Could the server simply send out data periodically without being prompted, while any clients in range silently listen? I am open to any other suggestions for the best way to get my serialized data to the client tablets.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
