【问题标题】:multiclient java client server chat多客户端 java 客户端 服务器 聊天
【发布时间】:2016-04-09 09:45:30
【问题描述】:

我正在尝试编写一个多客户端服务器聊天。一切都应该在同一台计算机上运行,​​每个客户端都在不同的 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);
                //  }   
                //}
            //});
        }

    }
}

【问题讨论】:

    标签: java multithreading server client chat


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

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

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

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

    }

    【讨论】:

      【解决方案2】:

      客户端需要两个线程:

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

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

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

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

      【讨论】:

      • 实际上是的,现在我在客户端只有一个线程(主线程)。过去,我有第二个线程从服务器接收消息,但它不起作用。所以我把它扔了。
      猜你喜欢
      • 2017-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-07
      • 1970-01-01
      • 2018-10-04
      • 2015-06-27
      • 1970-01-01
      相关资源
      最近更新 更多