I have a simple client-server app on android. the android service communicates with the server via tcp sockets. the service sends a simple String to server which works. the server processes the string and sends back an object to the android service. the object implements the serializable interface. the object "leaves" the server successfully but at the point where the android service receives the object (socket.readObject()) I get to following exception:
java.net.SocketException: Bad socket
I've never seen this. What does that mean?
Edit:
Method where exception gets thrown:
private static void startContextListener(){
new Thread(){
public void run(){
try{
while(contextsocket != null && !contextsocket.isClosed() && inContext.readObject() != null){
kontext = (Kontext) inContext.readObject();
}
}
catch(Exception e){
Log.e(TAG, "startContextListener(): " + e.toString());
}
}
}.start();
}
This is usually a result of read(2) on invalid socket descriptor ([EBADF] fildes is not a valid file or socket descriptor open for reading) so it looks that some layer of the app is closing the socket. Can you post more code to demonstrate how you work with the socket?
Related
I am trying to write a simple android chat app. I have created a service class which handles all the networking communication. The DatagramSocket binding is in a separate thread. Once in while I am getting this error and the app crashes:
java.net.BindException: bind failed: EADDRINUSE (Address already in use)
at libcore.io.IoBridge.bind(IoBridge.java:89)
at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
at java.net.DatagramSocket.<init>(DatagramSocket.java:78)
and this is the code which prodruces it. The error occur on the line with new DatagramSocket How can I avoid this error? Thank you.
private class ComThread extends Thread {
private static final int BCAST_PORT = 8779;
DatagramSocket mSocket;
InetAddress myBcastIP, myLocalIP;
public ComThread() {
try {
myBcastIP = getBroadcastAddress();
if (D)
Log.d(TAG, "my bcast ip : " + myBcastIP);
myLocalIP = getLocalAddress();
if (D)
Log.d(TAG, "my local ip : " + myLocalIP);
if (mSocket == null) {
mSocket = new DatagramSocket(BCAST_PORT);
mSocket.setReuseAddress(true);
mSocket.setBroadcast(true);
}
} catch (IOException e) {
Log.e(TAG, "Could not make socket", e);
}
}
Since Sean asked for the code, I have translated Nikola's answer to the following code, which is similar to what I am using in my app, in case it is useful:
if (mSocket == null) {
mSocket = new DatagramSocket(null);
mSocket.setReuseAddress(true);
mSocket.setBroadcast(true);
mSocket.bind(new InetSocketAddress(BCAST_PORT));
}
You need to set SO_REUSEADDR before binding. Don't specify port in the constructor - create unbound socket instead with DatagramSocket(null), then set options, then bind() explicitly.
Another reason that I faced,
In case you access a method that using your socket from an external thread, you have to make sure that the thread won't access the method more than once in the same time(or in another words won't create the socket more than one time), and despite the send and receive methods of the DatagramSocket are threadsafe, the construction of the DatagramSocket object is not, so you have to just synchronize the method that is capable of creating the DatagramSocket socket:
synchronized public void my_datagram_socket() throws Exception{
// create the socket
// operations through the socket
// whatever you want
}
In my android application I want to use the autobahn library to use websockets.
I have done server side code using spring.
Simple socket is working when i am try pub sub then i get error.
My Code :-
final String wsuri = "ws://localhost:8080/ws";
try {
mConnection.connect(wsuri, new Wamp.ConnectionHandler()
#Override
public void onOpen() {
Log.d(TAG, "Status: Connected to " + wsuri);
mConnection.subscribe("ws://localhost8080/ws/onetoone",
MyEvent1.class, new Wamp.EventHandler() {
#Override
public void onEvent(String topicUri, Object event) {
Log.d(TAG, "Status: Connected to " + event);
}
});
}
#Override
public void onClose(int code, String reason) {
Log.d(TAG, "Connection lost." + " " + reason);
}
});
} catch (Exception e) {
Log.d(TAG, e.toString());
}
OutOut :-
de.tavendo.autobahn.WebSocketConnection: created
de.tavendo.autobahn.WebSocketReader: created
de.tavendo.autobahn.WampReader: created
de.tavendo.autobahn.WampConnection: reader created and started
de.tavendo.autobahn.WebSocketWriter: created
de.tavendo.autobahn.WampWriter: created
de.tavendo.autobahn.WampConnection: writer created and started
de.tavendo.autobahn.WebSocketReader: running
de.tavendo.autobahn.WebSocketReader: run() : WebSocketException
(de.tavendo.autobahn.WebSocketException: RSV != 0 and no extension negotiated)
de.tavendo.autobahn.WebSocketReader: ended
de.tavendo.autobahn.WebSocketConnection: opening handshake received
Status: Connected to ws://localhost:8080/Spring4WebSocket/add
de.tavendo.autobahn.WebSocketConnection: fail connection [code = 4, reason = WebSockets protocol violation
de.tavendo.autobahn.WebSocketReader: quit
de.tavendo.autobahn.WebSocketConnection: waiting for reader to finish
de.tavendo.autobahn.WebSocketConnection: readr thread done
de.tavendo.autobahn.WebSocketConnection: sending close message over socket
de.tavendo.autobahn.WebSocketWriter: ended
de.tavendo.autobahn.WebSocketConnection: waiting for writer to finish
de.tavendo.autobahn.WebSocketConnection: writer thread done
Connection lost. WebSockets protocol violation
I have pass ip address place on local host(my PC ip address).
Any have solution for how to solve web Sockets protocol violation in android autobahn.
Please help for above problem.
The error message:
RSV != 0 and no extension negotiated
implies that one or more of the reserved bits of a WebSocket frame which your WebSocket client received from your WebSocket server was not 0. If no WebSocket extension was negotiated (during the WebSocket opening handshake) as the error message claims, the reserved bits should be all zeros.
Check whether the endpoint of your WebSocket server is properly speaking the WebSocket protocol.
I am using Tcp Sockets For Communication Between CLR C++ (Server) to Android(Client) While using .Net For GUI.
While the data is communicated and received. Using a Background Worker in C++ Application
if(backgroundworker1->CancellationPending)
{
listenerSocket->Close(); // Listener Socket is Closed
netStream->Close();
serverSocket->Close();
serverSocket->Shutdown(SocketShutdown::Both);
e->Cancel;
break;
}
While in Android i am using Async Class for Execution and receiving text from socket to a Handler. While in Doinbackground Function i am using this code.
try
{
socket = new Socket(dstAddress, dstPort);
BufferedReader inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do
{
try
{
if (!inputStream.ready())
{
if (message != null)
{
MainActivity.handler.obtainMessage(0, 0, -1,"Server: " + message).sendToTarget();
message = "";
}
}
int num = inputStream.read();
message += Character.toString((char) num);
Log.e(message,message);
}
catch (Exception classNot)
{
Log.e("Client TASK","classnot exception");
}
}
while (!message.equals("bye"));
inputStream.close();
socket.close();
}
I don't understand While am sending the Bye Message from the server and (Backgroundworker1->CancellationPending)
All server sockets are closed and Mobile Sockets are closed why is the UI Not Responding? Please Help..
The Problem was in Client in doinbackground Which calls the while loop again hence causing an exception because no data was received in the sockets and causing an exception. Finally added some sleep to the client that after some time the client query the server while if there is no message from the server the client shutdowns and shifted to postexecution function.
I am doing socket programming. I took reference from below link:
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
Below is detail about my issue. I have created Android lib for this ServerThread (my project requirement), and this is used in test app.
Now test app connect to this through lib and do the process. First time it works perfectly fine, but if I closed and reopen it crashed with exception:
"EADDRINUSE (Address already in use)"
Also tried serverSocket.setReuseAddress(true) this but no luck.
My code:
public void run() {
Socket socket = null;
try {
serverSocket = new ServerSocket(SERVER_PORT);
serverSocket.setReuseAddress(true);
} catch (IOException e) {
Log.e(TAG, "exception1= " + e.getMessage());
}
while (!Thread.currentThread().isInterrupted()) {
try {
socket = serverSocket.accept();
Log.d(TAG, "server Connected.......!!!!");
communicationThread = new CommunicationThread(
socket);
commThread = new Thread(communicationThread);
commThread.start();
} catch (IOException e) {
Log.e(TAG, "exception 2=" + e.getMessage());
}
}
}
If I call serverSocket.close() I am getting exception 2 as server socket close. Communication thread is same as given in previous link.
You have to call setReuseAddress(true) before the socket is bound to the port. You are calling it after, because you are passing the port to the constructor, which will bind the socket immediately.
Try this instead:
serverSocket = new ServerSocket(); // <-- create an unbound socket first
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(SERVER_PORT)); // <-- now bind it
TCP (and probably some other) sockets can't reuse the same port for a period after closing. This is to prevent confusion if there's data on the network from an existing connection. You can override this behavior, but the default is to wait for a period of time before allowing reuse of the port.
The call to fix this is setReuseAddress(true) on the server socket. But I'm not sure if it needs to be called on the first socket or the second, or both.
Edit:
Here's a blog post describing the TCP socket TIME_WAIT state and why it exists: http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html
While other answers pointed out the importance of setReuseAddress(true), another problem that could arise is to construct the ServerSocket twice and call bind with the same parameters. For example if you call twice the code run() of the question, serverSocket will be assigned to a new instance of the ServerSocket class, but the old one is still living until garbage collected. Now constructing with the port value as parameter equals to bind the ServerSocket object, and you are going to end up with two ServerSocket bound to the same address, which is forbidden hence the exception. So build your serverSocket with your chosen port only once!
Try to create the instance of SocketServer outside of the run() method.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
try {
// create a new instance of an unbound socket first
serverSocket = new ServerSocket();
} catch (IOException e) {
e.printStackTrace();
}
}
I'm developing an Android real-time-data app that sends data (floats and ints) to a server on the local subnet via a TCP socket. The problem I'm facing is that after sending some data simultaneously the socket doesn't send anymore data at all. I debugged the app and it shows that data is being sent but doesn't show up on the server. After this happens if I close the connection the server doesn't even get the notification that the connection has been terminated which it should according to my design model. Meanwhile I get an exception on the app saying it can not write to a broken pipe. This tells me that the problem is with the app because I also did test using a desktop app and I can send huge amounts of data to the server and it gets delivered.
And please keep in mind that the data size I'm talking about here is 252 bytes per packet.
Here's my class I'm using. (This runs in an AsyncTask object )
public class Network
{
private Socket handle;
public static enum TASK
{
TASK_CONNECT, TASK_SEND, TASK_CLOSE
}
public Network()
{
}
public String lastError = "";
public boolean Connect(String host, int port)
{
try
{
lastError = "Connecting to server.";
handle = new Socket(host, port);
handle.setTcpNoDelay(true); //
handle.setSendBufferSize(SIZE_OF_PACKET); ///==> These don't seem to help at all
handle.setKeepAlive(true); ///
return true;
}catch(IOException e)
{
lastError += e.getMessage() != null ? " "+ e.getMessage() : "";
return false;
}
}
private void err(String e){
System.err.println(e);
}
private boolean SendPacket(byte buffer[])
{
OutputStream oStream = null;
err("sending: " + buffer.length + " bytes");
try
{
lastError = "Obtaining output stream.";
oStream = handle.getOutputStream();
lastError = "Error sending data.";
oStream.write(buffer);
oStream.flush();
return true;
}catch(Exception e)
{
lastError += e.getMessage() != null ? " "+ e.getMessage() : "";
}
return false;
}
public void Close()
{
try{ handle.close(); handle = null; }catch(Exception e){} // swallow exception
}
}
I send my data in a loop depending on how many numbers I have. I tried a Google search but didn't find anything relevant. Has anyone experienced this before? It's making me mad now.
EDIT: Wireshark shows incoming "red" packets that don't reach the desktop app (server)
Look at this picture.
You can see the first few have Len > 0 the red ones have 0.
I think it's time Google interfaced the USB so we can use it. At least that'd would have been my first option.
Should you not be calling oStream.close() after you flush the stream, given that you never use it again?
Also, you say that this is being run in an AsyncTask object. Is it possible that multiple threads could be attempting to send packets at the same time? If so, you might need some form of synchronisation around the SendPacket method.
Ok. I solved the issue by using UDP instead. Thank you all.
But I still didn't find the source of the problem.