Сокет сервера Java застрял при приеме вызова (клиент Android, сервер Java) - PullRequest
1 голос
/ 20 декабря 2010

Ниже я поместил фрагмент кода, чтобы помочь понять мою проблему. У меня есть код сервера, отлично работает в первый раз, клиент загружает и отправляет пакет. После получения первого пакета сервер застревает на «принять».

У меня настроен wireshark для этого порта, и сервер получает эти пакеты. Мне просто интересно, почему принять не вернется больше, чем один раз. Это сводит меня с ума.

Код сервера

 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     
                                    }
    }
   }
  }
 }

Код клиента

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;
 }
}

Ответы [ 3 ]

3 голосов
/ 20 декабря 2010

Я не вижу установленного тайм-аута на serverSocket.

ServerSocket.accept() - это операция блокировки, поэтому она будет блокироваться до тех пор, пока не произойдет ошибка, не истечет время ожидания или не будет принято соединение.

Попробуйте

SererSocket.setSOTimeout(10000)

Вы также не закрываете свои потоки, когда закончите.

2 голосов
/ 20 декабря 2010

Вы уверены, что он застревает на вызове? Вы получили трассировку стека, которая показывает, что он ожидает принятия?

Предполагая, что это застревает в другом месте, мне интересно, не так ли это, потому что clientConnQ содержится в одном из ваших DA экземпляров. Синхронизированный блок охватывает раздел // Сделайте что-нибудь полезное здесь .

Интересно, может ли это сработать, если вы измените код на

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

Как только вы получите свой clientSocket из clientConnQ , никакой другой экземпляр не сможет обработать этот сокет.

0 голосов
/ 21 декабря 2010

Хорошо, если я получал $ за каждый раз, я задавал глупый вопрос:)

Здесь идет. Клиентский сокет подключается, и это происходит, когда сервер получает вызов на прием. По какой-то глупой причине я ждал подтверждения получения дальнейших данных от клиента. На самом деле, я должен просто подождать что-то в «потоке», а затем обработать поток. Я не должен ждать подтверждения для этого соединения.

Accept вызывается для «подключения» к сокету, а не для непрерывного получения данных.

Спасибо за вашу помощь. Вы заставили меня задуматься о синхронизации потоков, дизайне, сокетах в целом и, наконец, прийти к этому решению.

Фантастические отзывы людей. Благодарю. Сиддхарт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...