我的套接字服务器循环类是否正确?

时间:2014-12-16 21:05:28

标签: java multithreading sockets

当客户端的消息类型为“connect”时,我的服务器出现错误,这很奇怪。

服务器接收器代码:

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

客户端连接代码:

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 :(得分:2)

从您提交的代码中,客户端看起来很好,但服务器有一些问题。

创建服务器套接字时,必须指定要绑定的端口(在构造函数中)。这定义了您在哪个端口上侦听并等待客户端。

绑定套接字侦听后,调用.accept()接受客户端传入连接。 .accept()方法将返回表示已连接客户端的套接字。通常,您将循环.accept()并在每次返回时生成一个线程来处理新客户端(您可能有多个客户端)。要与客户端通信,您需要使用返回的套接字。

在您的代码中,您似乎使用的是未绑定的服务器套接字,而link客户端套接字绝对不是来自.accept()

编辑:正如Joachim指出的那样,你还需要通过打破循环来处理套接字关闭的情况。例如。

答案 1 :(得分:0)

这是完全错误的。这种代码一次只能正确处理一个客户端。

  • 一种方式或另一种方式,调用accept()的结果必须是在其自己的线程中执行的新Runnable,并且其run()方法构造其自己的所有流并调用在接受的套接字上执行所有I / O的方法。

  • 这一切都不会发生在Runnable的构造函数中,它仍然是接受循环线程的一部分。

  • 接受的套接字和那些流必须是Runnable的实例成员不是服务器类的实例成员。循环通常看起来像这样:

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

    其中ConnectionHandler如上所述实现Runnable

  • 请注意,循环没有做任何其他事情,特别是它不会改变它所属的类中的任何实例状态。