Siddharth
Siddharth

Reputation: 9584

Java Server socket stuck on accept call (Android Client, Java Server)

Below I have put a fragment of code to help understand my problem. I have a server code, works fine for the first time the client loads and sends a packet. After the first packet is received, the server is stuck on "accept".

I have wireshark configured for this port, and the server is getting those packets. I just wonder why accept wont return more than once. Its driving me nuts.

Server Code

 public class DAPool implements Runnable {
 private ServerSocket serverSocket;
 private ArrayList<DA> pool;
 private LinkedList<Socket> clientConnQ;
 public DAPool(int newPoolSize, int serverPort) {
  try {
     serverSocket = new ServerSocket(serverPort, 500, InetAddress.getByName("127.0.0.1"));
  } catch (IOException e) {
     e.printStackTrace();
     return;
  }
  poolSize = newPoolSize;
  clientConnQ = new LinkedList<Socket>();
  pool = new ArrayList<DA>(poolSize);
                DA deviceThread;
  for (int threads = 0; threads < poolSize; threads++) {
     deviceThread = new DA();
     connPool.add(deviceThread);
     deviceThread.start();
  }
 }
 public void run() {
    while (true) {
       Socket incomingSocket;
       try {
           incomingSocket = serverSocket.accept();
       } catch (IOException e) {
           e.printStackTrace();
       return;
     }
     insertNewConnToQ(incomingSocket);
  }
 }


 private class DA extends Thread {
  private Socket clientSocket;
  private ObjectInputStream inputObjectStream;
  public DA() { 
  }
  public void run() {
   while (true) {

    while (clientConnQ.isEmpty()) {
     synchronized (clientConnQ) {
      try {
       clientConnQ.wait();
      } catch (InterruptedException ignored) {
       ignored.printStackTrace();
      }
     }
    }
    synchronized (clientConnQ) {
     clientSocket = (Socket) clientConnQ.removeFirst();
     try {
      inputObjectStream = new ObjectInputStream(clientSocket.getInputStream());
     } catch (IOException e) {
      e.printStackTrace();
      return;
     }
        // Do something useful here     
                                    }
    }
   }
  }
 }

Client Code

public class SendQueue extends Thread {
 LinkedList<Message> requestQ;
 Message sendRequest, requestMessage;

 Socket clientSocket;
 OutputStream outputStream;
 ObjectOutputStream objectOutputStream;

 public SendQueue(Socket newClientSocket) {
  requestQ = new LinkedList<Message>();
  clientSocket = newClientSocket;
 }

 public void run() {
  while (true) {
   synchronized (requestQ) {
    while (requestQ.isEmpty()) {
     try {
      requestQ.wait();
     } catch (InterruptedException ignored) {
      ignored.printStackTrace();
     }
    }
    sendRequest = requestQ.removeFirst();
   }
   try {
    outputStream = clientSocket.getOutputStream();
    objectOutputStream = new ObjectOutputStream(outputStream);    
    objectOutputStream.writeObject(sendRequest);
    objectOutputStream.flush();
    outputStream.flush();
   } catch (IOException e) {
    e.printStackTrace();
   } catch (RuntimeException e) {
    e.printStackTrace();
   }
  }
 }

 public int sendRequest(Message message) {
  synchronized (requestQ) {
   requestQ.addLast(message);
   requestQ.notify();
  }
  return 0;
 }
}

Upvotes: 1

Views: 5896

Answers (3)

Siddharth
Siddharth

Reputation: 9584

Ok, if I got a $ for everytime I asked a silly question :)

Here goes. A client socket connects and thats when a server receives a accept call. For some silly reason I was waiting on accept for receiving further data from the client. Infact, I should just wait for something on the "stream" and then process the stream. I should not wait on the accept for that connection.

Accept is to be called to "connect" to the socket, not to receive data continuously.

Thanks for your all your help. You forced me to think about thread synchronization, the design, sockets in general and finally arrive that the solution.

Fantastic responses people. Thanks. Siddharth

Upvotes: 0

Richm
Richm

Reputation: 173

Are you sure that it is sticking on the accept call? Did you get a stacktrace that shows it waiting on accept?

Assuming it is getting stuck elsewhere I'm wondering if it isn't because clientConnQ is being held in one of your DA instances. The synchronized block covers the // Do something useful here section.

I wonder if it might work if you changed the code to be

synchronized (clientConnQ) {
    clientSocket = (Socket) clientConnQ.removeFirst();
}
try {
    ...

Once you have your clientSocket from clientConnQ then no other instance can process that socket.

Upvotes: 2

Kevin D
Kevin D

Reputation: 3594

I don't see a timeout being set on the serverSocket.

ServerSocket.accept() is a blocking operation so it will block until either an error occurs, a timeout occurs, or a connection is accepted.

Try

SererSocket.setSOTimeout(10000)

You also don't seem to be closing your streams when your finished.

Upvotes: 3

Related Questions