聊天服务器。线程问题

时间:2011-12-29 17:11:44

标签: java sockets chat

你可以帮助我使用这段代码,因为我尝试使用If语句但是没有用。我并没有要求为我写代码只是指着我。

主要的问题是,每次有人连接时,都会制作新的线程但是当他关闭聊天框时,脚踏板会保持打开并且不能正常工作。我的意思是有些人自己建立了10个连接,没有其他人可以聊天。

import java.net.*;
import java.io.*;

public class myServer {

    static ServerSocket server;
    static Socket client;
    static DataInputStream in;
    static DataOutputStream out;
    static clientThread t[] = new clientThread[10];

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

        System.out.println("Starting Server");
        server = new ServerSocket(7555);
        System.out.println("Started Server");

        while (true) {

            client = server.accept();
            System.out.println("CONNECTION");
            out = new DataOutputStream(client.getOutputStream());
            out.writeUTF("Welcome to the chat room");
            for (int i = 0; i <= 9; i++) {
                if (t[i] == null) {
                    (t[i] = new clientThread(client, t)).start();
                    break;
                }
            }
        }

    }

}

class clientThread extends Thread {

    DataInputStream in;
    DataOutputStream out;
    static String msg;
    Socket client = null;
    clientThread t[];

    public clientThread(Socket client, clientThread[] t) {
        this.client = client;
        this.t = t;
    }

    public void run() {

        try {
            in = new DataInputStream(client.getInputStream());
            out = new DataOutputStream(client.getOutputStream());
            boolean tru = true;

            while (tru) {
                msg = in.readUTF();
                System.out.println(msg);
                for (int i = 0; i <= 9; i++)
                    if (t[i] != null) {
                        t[i].out.writeUTF(msg);
                        System.out.println(t[i]);
                    }
            }
        } catch (IOException e) {
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您的问题不在于线程保持打开,而是您没有将客户端线程标记为已完成的机制。即使线程已退出,t[i]也不会成为null。它仍然会引用一个线程的实例 - 只是一个“死”线程。

以下是两种解决方法:

  1. 在线程退出之前,标记t[i] = null(其中i是当前线程的索引)。请注意,您需要在每个帖子中存储i的值。

    1. 修改clientThread并添加private int threadIndex;作为成员变量。
    2. 修改clientThread的构造函数并添加threadIndex作为参数。

      public clientThread(Socket client, clientThread[] t, int threadIndex) 
      {
          this.threadIndex=threadIndex;
          //...
      }
      
    3. run的右大括号之前,添加

      synchronized(t){t[this.threadIndex]=null;}
      
  2. 使用Executor并将clientThread提交给它。 Java的Executor将为您处理清理线程。

答案 1 :(得分:1)

为什么只为一个套接字连接创建10个线程?我想你想要为每个到聊天服务器的传入连接创建一个ClientThread。然后将该单个ClientThread添加到活动聊天列表中。当聊天客户端终止会话时,从该列表中删除该条目。您不需要将Thread实例或ClientThreads数组传递给ClientThread的构造函数,因为它本身就是这样。只需将Socket实例传递给ClientThread,并引用ChatServer即可。如果您正在尝试创建聊天室。然后允许服务器处理向其他人发送消息:

public class ChatServer {
    List<ClientThread> activeParticipants;

    public void say( ClientThread author, String message ) {
        for( ClientThread current : activeParticipants ) {
           if( current != author ) {
              current.send( message ); // this method will send a message to that client
           }
        }
    }
}

您需要使用两个线程,或使用InputStream.available()方法检查是否某些输入位于System.in或套接字的输入流中。这将允许您读取进入的消息以及允许用户同时键入消息。阻塞read()方法意味着在输入某些数据或接收数据之前,您无法看到消息。

同时将欢迎消息移动到ClientThread中,这样就不会使用两个不同的DataOutputStreams调用Socket.getOutputStream()两次。

答案 2 :(得分:0)

两次调用方法client.getOutputStream(),每次构建一个DataOutputStream。尝试直接在ClientThread中欢迎用户。