我正在写一个服务器 - 客户端聊天程序 . 服务器正确等待传入连接并创建一个线程( IdentThread )来验证用户(询问用户名和密码) . 在确认用户的身份后, IdentThread 创建 ChatThread ,处理用户输入并向其他用户及其关联的客户端发送消息 .

客户端程序通过 Buffered Reader 从命令行读取,使用 PrintWriter 将消息发送到服务器,并使用另一个 BufferedReader 接收消息 .

这种模式运作良好 . 但是,当用户断开连接然后重新连接时,它们会足够好地通过 IdentThread ,但在输入 ChatThread 时,服务器或其他用户的任何消息都不可见 . 我发现的唯一方法是重新启动服务器程序,这对于实际使用是不可行的 .

服务器启动一个新的 IdentThread ,将它传递给套接字,让它接受套接字并启动它 .

IdentThread 创建了一个新的 BufferedReaderPrintWriter 来处理 I/O . 无论客户端连接和断开连接多少次,这些都会一直工作 .

通过身份验证后, IdentThread 创建一个 ChatThread ,并将其传递给用户的套接字,用户名,ID号,BufferedReader和PrintWriter .

这是我遇到问题的地方 . 用户连接并断开连接一次后,他们就无法再读取服务器发送给他们的任何消息,尽管他们可以从 IdentThread 读取消息 . 用户发送的消息对其他用户可见,服务器正确响应用户发送的命令 .

我不确定问题是否是由于我从未有任何绑定到套接字的事实引起的,就像我正在进行通信工作或其他一些我不知道的问题 .

Edit: I cropped up some of my code and I've brought in the parts that deal with the communication.

I have a feeling that the issue might come from how I assign the ChatThreads to the clients

服务器主:

public class Main{

public static boolean listening = false;
public static AtomicInteger connec = new AtomicInteger(0);
public static AtomicInteger onln = new AtomicInteger(0);
public static Hashtable<String, String> passlist = new Hashtable<String, String>();
public static Hashtable<String, Integer> privslist = new Hashtable<String, Integer>();
public static String[] online = new String[20];
public static ChatThread[] clients = new ChatThread[20];

public static void main(String[] args) throws IOException{

    ServerSocket listener = null;
    int port = 6667;
    int backlog = 20;
    int maxconnec = 20;

    passlist.put("apoc326", "password");
    privslist.put("apoc326", 5);
    passlist.put("jameson", "password");
    privslist.put("jameson", 0);

    //create a new server socket
    listener = new ServerSocket(port, backlog);
    listening = true;
    System.out.println("Starting listening to the socket for an incoming connection.");

    //if the server is listening for new connections and
    //the maximum number of connections hasn't been reached
    while(listening == true && connec.get() < maxconnec){

        //create a new thread to perform user login and increment number of connections
        System.out.println("Listening...");
        new IdentThread(listener.accept()).start();
        connec.incrementAndGet();
    }

    //close the server socket
    listener.close();
}

}

IdentThread:

public class IdentThread extends Thread{

private Socket mysock = null;
private PrintWriter out = null;
private BufferedReader in = null;

IdentThread(Socket sock){

    mysock = sock;
}

public void run(){

    try{
        out = new PrintWriter(mysock.getOutputStream(), true);
        in = new BufferedReader(new InputStreamReader(mysock.getInputStream()));

            //A whole mess of code removed

    if(validName == true && validPass == true){
        synchronized(this){
            for(int i = 0; i < Main.clients.length; i++){
                if(Main.clients[i] == null){
                    //add the user's name to the list of online users
                    ID = i;
                    Main.online[i] = username;
                    Main.clients[i] = new ChatThread(mysock, username, ID, in, out);
                    Main.clients[i].start();
                    Main.onln.incrementAndGet();

ChatThread:

public class ChatThread extends Thread{

private Socket mysock = null;
private PrintWriter out = null;
private BufferedReader in = null;
private boolean online = true;
private String input = null;
private String output = null;
private int ID = -1;

//constructor
ChatThread(Socket sock, String name, int ID, BufferedReader in, PrintWriter out){

    mysock = sock;
    username= name;
    alias = name;
    this.in = in;
    this.out = out;
    this.ID = ID;
    privs = Main.privslist.get(username);

}

//executable section of the thread
public void run(){

    while(online == true){


            try {
                input = in.readLine();
            } 
            catch (IOException e) {
                e.printStackTrace();
                break;
            }

            output = parse(input);

            if(output != null){
                sendAll(output);
            }
    }

    try {
        in.close();
        out.close();
        mysock.close();
        Main.onln.decrementAndGet();
        Main.connec.decrementAndGet();
        System.out.println(username + " has disconnected. Online user count: " + Main.onln.get());
        System.out.println("ChatThread " + ID + " terminating. Connection count: " + Main.connec.get());
    } 
    catch (IOException e) {
        e.printStackTrace();
    }
}

客户:

public class Main {

public static void main(String args[]) throws IOException{

    BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    String servIP = null;
    int port = 6667;
    PrintWriter out = null;
    BufferedReader in = null;
    Socket mysock = null;
    boolean connected = false;
    String incoming = null;
    String outgoing = null;

    servIP = console.readLine();

    mysock = new Socket(servIP,port);

    out = new PrintWriter(mysock.getOutputStream(), true);
    in = new BufferedReader(new InputStreamReader(mysock.getInputStream()));

    connected = true;

    while(connected == true){

        while(in.ready()){
            incoming = in.readLine();
            System.out.println(incoming);
        }

        while(console.ready()){
            outgoing = console.readLine();
            out.println(outgoing);

            if(outgoing.equals("/disco")){
                connected = false;
                break;
            }
        }
    }

    in.close();
    out.close();
    console.close();
    mysock.close();
}