多客户端java服务器聊天

时间:2016-01-05 14:20:21

标签: java multithreading server client chat

我正在尝试编写多个客户端服务器聊天。一切都应该在同一台计算机上运行,​​每个客户端都在不同的shell终端控制台中。我在这方面阅读了几个线程,人们说,我应该在服务器上为每个连接的客户端运行新线程。这就是我所做的。但是,服务器在其控制台上打印来自每个客户端的消息,但客户只能看到他们写的消息,而不是每次聊天时提交的消息。我该怎么做才能解决它?

这是代码: 服务器:

//package javauj.serwer;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;


public class Server {
    private static final int PORT_NUM = 5051;
    private static ServerSocket serS;
    private static Socket s;

    public static void main(String[] args) throws IOException{
        DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
        Calendar cal = Calendar.getInstance();
            System.out.println(df.format(cal.getTime())+" Server waiting on port "+PORT_NUM);
            try {
                serS = new ServerSocket(PORT_NUM);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



        while(true){
            try {
                s = serS.accept();
                System.out.println("New user connected");
                    ServerThread st=new ServerThread(s);
                        st.start();


                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   





        }
    }
}   

服务器线程:

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Scanner;


public class ServerThread extends Thread {
    Socket socket=null;
    private Scanner sc;
    private PrintStream ps;
    public ServerThread(Socket s) {
        this.socket=s;

    }



        public void run(){
            DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
            Calendar cal = Calendar.getInstance();
            String response;    
                while(true){    
                try {
                        sc = new Scanner(socket.getInputStream());
                        ps = new PrintStream(socket.getOutputStream());
                } catch (IOException e) {
                            // TODO Auto-generated catch block
                        e.printStackTrace();
                }

                if((response=sc.nextLine())!=null){


                    System.out.println(df.format(cal.getTime())+" Napisal "+response);

                    ps.println(df.format(cal.getTime())+" Napisal :"+response);

                    }   
            }


        }


}

和客户

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;




public class Client {
    static Scanner sc;
    static Scanner sc2;
    static Socket s;
    static String response;
    public static void main(String[]args) throws UnknownHostException, IOException{
        String send;
        sc=new Scanner(System.in);  //client send scanner
        s = new Socket("127.0.0.1", 5051);
        sc2 = new Scanner(s.getInputStream());  //client response scanner
        PrintStream ps = new PrintStream(s.getOutputStream());

        while(true){

            System.out.println(">");    
            send = sc.nextLine();

            ps.println(send);       
            // I tried run new thread for responses
            //Thread thread = new Thread(new Runnable(){
                //public void run(){
                    //while(true){
                        response=sc2.nextLine();        
                        System.out.println(response);
                //  }   
                //}
            //});
        }

    }
}

2 个答案:

答案 0 :(得分:2)

客户端需要两个线程:

  • 一个阅读来自服务器的消息
  • 另一个获取用户输入的线程

第一个线程(来自服务器的阅读器)只是读取传入的消息并将其打印到控制台

第二个线程(服务器的编写者)接受用户输入并将其发送到服务器。

实际上在你的代码中,客户端上只有一个线程(主线程)。

答案 1 :(得分:0)

  1. 您必须在ServerThread实例和服务器之间实现通信(例如通过接口)。必须通知服务器有关ServerThread获取的消息,然后将此消息转换为其他(先前建立的)套接字(必须跟踪)。

  2. 您的客户端有两个扫描程序,但其中一个实际上阻止了另一个在nextLine()调用上。因此,您必须在单独的线程中运行其中一个扫描程序。

  3. 以下代码适用于我,但必须考虑线程安全性:

    public interface MessageListener {
      void acceptMessage(String message);
    }
    
    public class Server {
      private static final int PORT_NUM = 5051;
      private static ServerSocket serS;
      private static List<PrintStream> sockets = new ArrayList<PrintStream>();
      public static void main(String[] args) throws IOException{
        DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        System.out.println(df.format(cal.getTime())+" Server waiting on port "+PORT_NUM);
        try {
            serS = new ServerSocket(PORT_NUM);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        MessageListener listener = new MessageListener() {
            @Override
            public void acceptMessage(String message) {
                Iterator<PrintStream> it = sockets.iterator();
                while (it.hasNext()) {
                    PrintStream ps = it.next();
                    ps.println("Have got message: " + message);
                }
            }
        };
    
        while(true){
            try {
                Socket s = serS.accept();
                sockets.add(new PrintStream(s.getOutputStream()));
                System.out.println("New user connected");
                ServerThread st=new ServerThread(s, listener);
                st.start();
    
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
    
    
        }
    }
    
    
    public class ServerThread extends Thread {
      Socket socket=null;
      private Scanner sc;
      //private PrintStream ps;
      private final MessageListener listener;
    
      public ServerThread(Socket s, MessageListener listener) {
        this.socket=s;
        this.listener = listener;
      }
    
      public void run(){
        DateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm:ss");
        Calendar cal = Calendar.getInstance();
        String response;
        while(true){
            try {
                sc = new Scanner(socket.getInputStream());
                //ps = new PrintStream(socket.getOutputStream());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            if((response=sc.nextLine())!=null){
    
    
                System.out.println(df.format(cal.getTime())+" Napisal "+response);
    
                //ps.println(df.format(cal.getTime())+" Napisal :"+response);
                listener.acceptMessage(response);
            }
          }
    
    
      }
    
    
    }
    
    public class Client {
      static Scanner sc;
      static Scanner sc2;
      static Socket s;
      static String response;
      public static void main(String[]args) throws UnknownHostException, IOException{
        String send;
        sc=new Scanner(System.in);  //client send scanner
        s = new Socket("127.0.0.1", 5051);
        ResponseListener l = new ResponseListener(new Scanner(s.getInputStream()));
        Thread t = new Thread(l);
        t.start();
    
        PrintStream ps = new PrintStream(s.getOutputStream());
    
        while(true){
    
            System.out.println(">");
            send = sc.nextLine();
    
            ps.println(send);
        }
    
    }
    
    static class ResponseListener implements Runnable {
        private final Scanner scanner;
    
        ResponseListener(Scanner scanner) {
            this.scanner = scanner;
        }
    
        @Override
        public void run() {
            while (true) {
                response = scanner.nextLine();
                System.out.println(response);
            }
        }
    }
    

    }