2014-12-16 3 views
0

Я получаю ошибки на своем сервере, когда тип сообщения клиента «подключается», это очень странно.Является ли мой класс шлейфов сервера Socket правильно?

сервера Код получателя:

package threads; 

public class ReceiveFromClientThread extends Thread { 

ObjectInputStream inFromClient = null; 
ServerSocket servs = new ServerSocket(); 
Socket link = null; 
Message m = null; 

public void run() { 

    try { 
     this.servs.servs.accept(); 
     this.inFromClient = new ObjectInputStream(link.getInputStream()); 
    } catch (SocketException e3) { 
     System.err.println(" Connection reset by peer."); 
    } catch (IOException e1) { 
     e1.printStackTrace(); 
    } 

    while(true) { 
     try { 
      if (link.isConnected()) { 
       this.m = (Message) inFromClient.readObject(); //SHOULDN'T THIS THREAD PAUSE HERE? 

       if (m.getType().equalsIgnoreCase("normal")) { 
         System.out.println("[" + m.getTimestamp() + "] " 
          + m.getOwner() + " -> " + m.getText()); 
         ServerMain.mc.pushMessageToList(this.m); //Added to message list. 
       } else if (m.getType().equalsIgnoreCase("connect")) { 
         System.out.println(m.getOwner() + " connected from " 
          + this.link.getInetAddress()+":"+this.link.getPort()); 
       } else if (m.getType() == "disconnect") { 
         System.err.println("[" + m.getTimestamp() + "] " 
          + "[Origin: " + m.getIp() + "] " + m.getOwner() 
          + " Disconnected."); 
       } 
      } 
     } catch (IOException | ClassNotFoundException e) { 
     } 
    } 
} 

public ReceiveFromClientThread(Socket link) { 
    this.link = link; 
} 
} 

Client Код соединения:

ClientMain.sock  = new Socket("127.0.0.1",21215); 
ClientMain.oos  = new ObjectOutputStream(sock.getOutputStream()); 

Message m = new Message(); 
     m = m.setType("connect"); 
     m.setOwner("Raphael"); 
     m.setIp(sock.getInetAddress().getHostAddress()); 
     m.setPcname(sock.getInetAddress().getCanonicalHostName()); 
     clientmain.ClientMain.oos.writeObject(m); 

Это должно работать, но это дает бесконечный цикл или иногда NullPointerException. Есть ли ошибка в моем коде? Не следует ли приостановить поток сервера на строке readObject()?

+2

Не могли бы вы предоставить полный код вашего Клиента? –

+0

Закрывает клиентский сокет после отправки сообщения? – Joachim

+0

Да, предоставляет ли StackOverFlow, где я могу поделиться кодом? – raphaelbgr

ответ

2

От части кода, который вы отправили, клиент выглядит хорошо, но на сервере есть несколько проблем.

При создании серверного сокета вы должны указать порт для привязки к (в конструкторе). Это определяет, на каком порту вы слушаете и ожидаете клиентов.

Как только у вас есть прослушивание со связанной связью, вы вызываете .accept(), чтобы принимать входящие соединения клиентов. метод .accept() вернет сокет, представляющий подключенный клиент. Обычно вы зацикливаетесь на .accept() и создаете поток каждый раз, когда он возвращается для обработки нового клиента (у вас может быть несколько клиентов). Чтобы связаться с клиентом, вам нужно использовать возвращаемый сокет.

В вашем коде вы, кажется, используете несвязанный серверный сокет, а ваш клиентский сокет link определенно не приходит от .accept().

Редактировать: Как указал Йоахим, вам также необходимо обработать случай, когда розетка закрыта, например, разбив петлю.

+0

Я попытался действительно ли адаптируйте код из оригинала, который намного сложнее написать здесь, позволяет ли StackOverFlow предоставить полный код? – raphaelbgr

+1

@raphaelbgr no, для этого вам нужно вставить свой код на другой сайт и поместить ссылку – ElderBug

0

Это совершенно неправильно. Такой код может корректно обрабатывать только одного клиента за раз.

  • Так или соседний, результат вызова accept() должен быть новый Runnable, который выполняется в своем собственном потоке, и чей run() метод строит все свои собственные потоки и вызовы методов, которые делают все I/O на принятый сокет.

  • Ничего из этого не должно произойти в этом конструкторе Runnable, который все еще является частью потока цикла принятия.

  • Принимаемый сокет и те потоки должны быть членами-экземплярами Runnable, не класса сервера. Петля более обычно выглядит примерно так:

    while (true) 
    { 
        new Thread(new ConnectionHandler(ss.accept())).start(); 
    } 
    

    где ConnectionHandler реализует Runnable, как описано выше.

  • Обратите внимание, что цикл ничего не делает, и в частности, что он не изменяет никакого состояния экземпляра в классе, в котором он является частью.

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