多线程服务器聊天Java - 连接但没有消息

时间:2017-04-12 10:12:34

标签: java multithreading serversocket

尝试构建一个通过命令提示符运行的简单多线程聊天服务器。客户端确实连接到服务器,服务器将容纳多个客户端,但是当尝试将消息从一个客户端发送到另一个客户端,或者甚至通知客户端登录的另一个用户时,客户端命令提示符上没有任何内容。

public class Server {
private static ServerSocket servSock;
private static Socket clientSock;
private static ArrayList<ClientThread> clientList;
private static int IDcount = 0;


public static void main(String args[]){
      // Get command line arguments.
      if (args.length != 3) {
         System.out.println("Required arguments: server port, block duration, timeout");
         return;
      }
      int port = Integer.parseInt(args[0]);
      int blockDur = Integer.parseInt(args[1]);
      int timeout = Integer.parseInt(args[2]);

      try{
      servSock = new ServerSocket(port);
      clientList = new ArrayList<ClientThread>();
      }
      catch(IOException ex){
          System.err.println(ex);
      }


      while (true) {
        try {
          clientSock = servSock.accept();
          ClientThread thread = new ClientThread(clientSock);
          clientList.add(thread);
          thread.start();
        } catch (IOException e) {
          System.out.println(e);
        }
      }
    }

private synchronized static void broadcast(String msg){
    System.out.print(msg);
    for(int i = 0; i < clientList.size(); i++){
        ClientThread client = clientList.get(i);
        client.send(msg);
    }

}

synchronized static void unlist(int id){
for(int i = 0; i < clientList.size(); i++){
    ClientThread thread = clientList.get(i);
    if(thread.id == id){
        clientList.remove(i);
        return;
        }
    }
}

static class ClientThread extends Thread {
    Socket sock;
    BufferedReader tIn;
    PrintWriter tOut;

    int id;
    String username;
    String msg;

    ClientThread(Socket sock){
        id = IDcount++;
        this.sock = sock;
        try{
            tIn = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            tOut = new PrintWriter(sock.getOutputStream());
            username = tIn.readLine();
            broadcast(username + " logged in");
        }
        catch(IOException ex){
            System.err.println(ex);
        }
    }

    public void run(){
        boolean loggedIn = true;
        while(loggedIn){
            try{
                msg = tIn.readLine();
            }
            catch (IOException ex){
                System.err.println(ex);
            }
            String[] parts = msg.split("\\s",2);
            String type = parts[0];

客户端代码类似

public class Client{
private static Socket clientSock;
private static BufferedReader in;
private static PrintWriter out;
private static Scanner scan;

public static void main(String[] args) throws IOException {
      if (args.length != 2) {
             System.out.println("Required arguments: server IP, server port");
             return;
          }
      String host = args[0];
      int port = Integer.parseInt(args[1]);

      clientSock = new Socket(host, port);
      in = new BufferedReader(new InputStreamReader(clientSock.getInputStream()));
      out = new PrintWriter(clientSock.getOutputStream());
      scan = new Scanner(System.in);

      new ListenFromServer().start();
      boolean online = true;

      System.out.println("Enter your username:");
      String username = scan.nextLine();

      out.println(username);

      while(online){
          System.out.println("> ");
          String msg = scan.nextLine();
          String[] parts = msg.split("\\s");
          String type = parts[0];
          send(msg);
          if(type.equalsIgnoreCase("logout")){
              online = false;
          }


      }
      logoff();
}

      static void send(String msg) throws IOException{
          out.println(msg);
      }

      private static void logoff() throws IOException{
              in.close();
              out.close();
              scan.close();
              clientSock.close();
      }

     static class ListenFromServer extends Thread{
         public void run(){
             while(true){
                 try{
                     String msg = in.readLine();
                     System.out.println(msg);
                 }
                 catch(IOException ex){
                     System.err.println(ex);
                 }
             }
         }
     }

    }

1 个答案:

答案 0 :(得分:0)

使用git reset --hard <SOME-COMMIT>发送数据时,数据会写入缓冲区。您必须在PrintWriter.println()之后调用PrintWriter.flush()以立即向服务器发送数据或从服务器发送数据。

当你在ClientThread构造函数中调用println时,你会阻塞主线程,因为构造函数在主线程中调用。因此,虽然连接用户不会发送用户名,但其他客户端无法连接。