2015-05-27 2 views
0

Я работаю с Java-сокетами. У меня есть серверный сокет и два клиентских сокета. Моя проблема заключается в том, что первый клиентский сокет отправляет свое сообщение на мой серверный сокет, а сообщение со второго клиентского сокета не поступает в сокет сервера. Это означает, что для первого клиентского сокета цикл while прерывается после успешного сообщения, а второй клиент заканчивается бесконечным циклом while. Если я тестирую каждый клиентский сокет отдельно в тестовом классе, каждый клиентский сокет правильно отправляет свое сообщение на мой серверный сокет. Наблюдая за TCPView, я заметил, что клиентский сокет не отвечает, пока используется мой порт.Нет ответа от второго клиентского сокета

Я читал, что второй клиентский сокет все равно должен отвечать на свое сообщение, даже если порт был использован. В моем случае второй клиентский сокет должен всегда отвечать примерно через секунду после первого. Но я не могу заставить их работать один за другим.

Итак, вот мой код метода, который ждет клиента сообщений:

public void listenToSocket() 
{ 
    serverSocket = null; 
    thread = null; 
    SocketAddress adress = new InetSocketAddress(CommunicationValues.SOCKET_PORT); 
    try { 
     serverSocket = new ServerSocket(); 
     serverSocket.setReuseAddress(true); 
     serverSocket.bind(adress); 

    } catch (IOException e1) { 
     // TODO Auto-generated catch block 
     e1.printStackTrace(); 
     System.exit(0); 
    } 




    while(true){ 
     try 
     { 
      Socket clientSocket = serverSocket.accept(); 
      thread = new SocketMessageThread(clientSocket); 
      thread.start();   

     } catch (IOException e) { 
      System.out.println("MyServerSocket caught an error: \n" + e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 

} 

Этот метод вызывается в потоке. Структура выглядит следующим образом:

  • SocketListenerThread вызывает метод listenToSocket() из класса SocketListener
  • listenToSocket() описано выше
  • SocketMessageThread обрабатывает сообщение вывода клиентского сокета в его методе run().

EDIT Вот код моего SocketMessageThread:

public class SocketMessageThread extends Thread{ 

private Socket clientSocket; 
private static int nameCounter = 0; 


public SocketMessageThread(Socket clientSocket) { 
    this.clientSocket = clientSocket; 
    this.setDaemon(true); 
    this.setName("SocketMessageThread" + (nameCounter++)); 
} 

public void run() { 
    try (
      BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) 
    { 
     while (in.ready()) 
     { 
      String inLine = in.readLine(); 
      CommunicationValues.MESSAGE_MEMORIZER = inLine; 
     } 
     clientSocket.close(); 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
}} 

EDIT 2 Оба клиенты взаимодействуют только с одним конкретным сообщением. Например. когда клиент запускается, он упомянул, что запуск был успешным с одним сообщением. Нет повторных сообщений, поступающих из клиентских сокетов, до тех пор, пока их не уловят серверные сокеты. Поэтому, если серверный сокет не поймает это сообщение, он исчез, и он не будет отправлен снова клиентским сокетом.

+0

Код сервера правильный, поскольку вы начинаете новый поток для каждого нового клиента и отправляете адрес сокета для каждого клиента. Для общения с каждым клиентом вам необходимо поддерживать разные входные выходные потоки. Напр. если есть два клиента: - клиент A и клиент B. Затем сервер будет принимать запрос на подключение 1-го, тогда поток будет обрабатывать дальнейший запрос, и поток будет связываться с клиентом, поддерживая отдельный выходной поток отдельно. –

+0

Я думаю, что сокет - это синхронный канал связи «один к одному».Если ваш первый клиент не выпускает сокет, второй никогда не сможет подключиться (сервер может также прервать связь, закрыть и снова открыть сокет для прослушивания других клиентов). –

+0

@francescoforesti Ваш комментарий не имеет смысла. Принятые сокеты независимы. Первому клиенту не нужно «освобождать сокет», чтобы второй клиент мог подключиться. Задержка прослушивания позаботится об этом, если ничего не сделает. В вопросе о том, что второй клиент не может подключиться, нет ничего. – EJP

ответ

1
while (in.ready()) 
{ 
    // ... 
} 

Классическое злоупотребление ready(). биржи все это:

String inLine; 
while ((inLine = in.readLine()) != null) 
{ 
    CommunicationValues.MESSAGE_MEMORIZER = inLine; 
} 

Предположительно есть еще код, который вы не показали нам: в противном случае все это будет сделать, это запомнить последнюю строку, посланную.

+0

Я попробую. Это .ready() - метод все время беспокоил меня. Но так как мой коллега написал образец кода и сказал мне, вот как работал его клиентский сокет, я его никогда не менял. – KJaeg

+0

Я пробовал, но это не сработало. Изменение кода таким образом, как это приводит к исключению NullPointerException. Помещение 'MESSAGE_MEMORIZER' в значение if с уловленными значениями Null приводит к бесконечному циклу while. Оба выполняются в ожидании первого клиентского сокета. Может быть, я должен упомянуть, что каждый клиент пишет сообщение по выходу только один раз (когда он уведомляет, что запуск программы был успешным). Использование 'in.ready()' вместо этого работает для первого клиента. Btw: Спасибо, что поделились своими идеями со мной. – KJaeg

+0

Нет 'NullPointerException', если вы скопировали вышеприведенный код, если входной поток не равен нулю. Если есть только одна строка для чтения, измените 'while' на' if'. – EJP

Смежные вопросы