zoukankan      html  css  js  c++  java
  • JAVA 无图形界面 单线程聊天程序

    起因

    想用JAVA做一个聊天室程序,学了TCP里Socket和ServerSocket,就蠢蠢欲动,写了一个只能回复一条才能看到收到的简单程序。

    知识点。

    客户端

    Socket client = new Socket("localhost",8888) ; // 客户端连服务器
    BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream())) ; // 输入流,之后用于读取
    PrintStream out = new PrintStream(client.getOutputStream()) ; // 输出流,发送数据

    服务器

    ServerSocket ss=new ServerSocket(8888);
    Socket byclient = ss.accept() ; // 这个client是服务器到客户端的socket; 注意后面IO流!!!得到连接,程序进入到阻塞状态
    out = new PrintStream(byclient.getOutputStream()) ; //输出流
    BufferedReader buf = new BufferedReader(new InputStreamReader(byclient.getInputStream())) ;// 输入流 !!!注意对比!准备接收客户端的输入信息

    问题

    想了很久都没法实现正常的聊天功能,要么只能接一条发一条就结束,要么就只能一直接。。。
    然后查了一下,发现需要用多线程的知识来解决这个问题

    代码

    我的简单聊天

    服务器端

    import java.io.*;
    import java.net.*;
    public class SERV {
        Socket cl;
        ServerSocket ser;
    
        public SERV() throws IOException {
            this.ser = new ServerSocket(9999);
            InetAddress inetAddr = InetAddress.getLocalHost();
            System.out.println("Connecting,LocalIP:"+ inetAddr.getHostAddress());
            this.cl = ser.accept();
            //System.out.println("Connected");
            PrintStream ot=new PrintStream(cl.getOutputStream());
            BufferedReader rd=new BufferedReader(new InputStreamReader(System.in));
            BufferedReader in= new BufferedReader(new InputStreamReader(cl.getInputStream()));
            ot.println("plz");
    
            while (true){
                System.out.println();
                    System.out.print("Client:");
                    String clt=in.readLine();
                    System.out.println(clt);
                    System.out.print("Message:");
                    String out = rd.readLine();
                    ot.println(out);
            }
    
        }
        public static void main(String[] args) throws IOException {
            SERV SERV=new SERV();
    
        }
    }
    

    客户端

    import java.io.*;
    import java.net.*;
    
    public class CL {
        Socket cl;
        public CL(String ip) throws IOException {
            this.cl=new Socket(ip,9999);
            System.out.println("OK");
            BufferedReader in= new BufferedReader(new InputStreamReader(cl.getInputStream()));
            BufferedReader rd=new BufferedReader(new InputStreamReader(System.in));
            PrintStream ot=new PrintStream(cl.getOutputStream(),true);
            ot.println("connected");
    
            while (true) {
                    System.out.print("Server:");
                    String sv = in.readLine();
                    System.out.println(sv);
                    System.out.println("Message:");
                    String msg = rd.readLine();
                    ot.println(msg);
            }
        }
        public static void main(String[] args) throws IOException {
            System.out.println("enter your dest-ip:");
            BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
            String ip= br.readLine();
            CL CL=new CL(ip);
        }
    }
    
    


    多线程

    客户端:

    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.Socket;
    import java.util.Scanner;
    //读线程
    class ReadFromServer implements Runnable{
        private Socket client;
        public ReadFromServer(Socket client) {
            this.client = client;
        }
        @Override
        public void run() {
            try {
                //获取输入流来取得服务器发来的信息
                Scanner in = new Scanner(client.getInputStream());
                while (true){
                    if (client.isClosed()){
                        System.out.println("客户端已经关闭");
                        in.close();
                        break;
                    }
                    if(in.hasNext()){
                        String msgFromServer = in.nextLine();
                        System.out.println("服务器发来的信息为:"+msgFromServer);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    //写线程
    class SendMsgToServer implements Runnable{
        private Socket client;
        public SendMsgToServer(Socket client) {
            this.client = client;
        }
        @Override
        public void run() {
            try {
                PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
                Scanner in = new Scanner(System.in);
                while (true){
                    System.out.println("请输入要向服务器发送的信息..");
                    String strFromUser = "";
                    if (in.hasNext()){
                        strFromUser = in.nextLine();
                    }
                    //向服务器发送信息
                    out.println(strFromUser);
                    //byebye
                    if (strFromUser.contains("byebye")){
                        System.out.println("当前客户端退出聊天室");
                        out.close();
                        in.close();
                        client.close();
                        break;
                    }
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    public class MutilThreadClient {
        public static void main(String[] args) throws IOException {
            //根据指定ip及端口号建立连接
            Socket client = new Socket("127.0.0.1",6666);
            //启动读线程和写线程
            Thread readThread = new Thread(new ReadFromServer(client));
            Thread sendThread = new Thread(new SendMsgToServer(client));
            readThread.start();
            sendThread.start();
        }
    }
    

    服务器:

    import java.io.IOException;
    import java.io.PrintStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Scanner;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    import java.util.Set;
    
    public class MutilThreadServer {
    
        private static Map<String,Socket> clientLists = new ConcurrentHashMap<>();
        //专门用来处理每个客户端的输入,输出请求
        private static class ExecuteClientRequest implements Runnable{
            private Socket client;
            public ExecuteClientRequest(Socket client) {
                this.client = client;
            }
            @Override
            public void run() {
                try {
                    //获取用户输入流,读取用户发来的信息
                    Scanner in = new Scanner(client.getInputStream());
                    String strFromClient = "";
                    while (true){
                        if (in.hasNext()){
                            strFromClient = in.nextLine();
                        }
                        //windows下消除用户输入自带的
                        Pattern pattern = Pattern.compile("
    ");
                        Matcher matcher = pattern.matcher(strFromClient);
                        strFromClient = matcher.replaceAll("");
    
                        /* 注册:username:xxx
                         * 群聊:G:群聊内容
                         * 私聊:P:用户名-私聊内容
                         * 用户退出:byebye*/
                        //注册流程
                        if (strFromClient.startsWith("username:")){
                            String username = strFromClient.split("\:")[1];
                            Register(username,client);
                        }
                        //群聊流程
                        if (strFromClient.startsWith("G:")){
                            String groupMsg = strFromClient.split("\:")[1];
                            groupChat(groupMsg);
                        }
                        //私聊
                        if (strFromClient.startsWith("P:")){
                            String username = strFromClient.split("\:")[1].split("\-")[0];
                            String privateMsg = strFromClient.split("\:")[1].split("\-")[2];
                            privateChat(username,privateMsg);
                        }
                        //用户退出:1:byebye
                        if(strFromClient.contains("byebye")){
                            String username = strFromClient.split("\:")[0];
                            userOffLine(username);
                            break;
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            private void Register(String username,Socket socket){
                clientLists.put(username,socket);
                System.out.println("用户"+username+"上线了!当前聊天室人数为:"+clientLists.size());
                try {
                    PrintStream out = new PrintStream(socket.getOutputStream(),true,"UTF-8");
                    out.println("注册成功");
                    out.println("当前聊天室人数为:"+clientLists.size());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //群聊——遍历map,向每个客户端输出一遍
            private void groupChat(String groupMsg) throws IOException {
                Set<Map.Entry<String,Socket>> clientEntry = clientLists.entrySet();
                Iterator<Map.Entry<String,Socket>> iterator = clientEntry.iterator();
                while (iterator.hasNext()){
                    //取出每一个客户端实体
                    Map.Entry<String,Socket> client = iterator.next();
                    //拿到客户端输出流输出群聊信息
                    PrintStream out = new PrintStream(client.getValue().getOutputStream(),
                            true,"UTF-8");
                    out.println("群聊信息为:"+groupMsg);
                }
    
            }
            //私聊
            private void privateChat(String username,String privateMsg) throws IOException {
                //取出username对应的Socket
                Socket client = clientLists.get(username);
                PrintStream out = new PrintStream(client.getOutputStream(),true,"UTF-8");
                out.println("私聊信息为:"+privateMsg);
            }
            private void userOffLine(String username){
                //删除map中的用户实体
                clientLists.remove(username);
                System.out.println("用户"+username+"已下线");
    
            }
        }
        public static void main(String[] args) throws Exception {
            ServerSocket serverSocket = new ServerSocket(6666);
            //使用线程池来同时处理多个客户端连接
            ExecutorService executorService = Executors.newFixedThreadPool(20);
            System.out.println("等待客户端连接");
            for (int i=0;i<20;i++){
                Socket client = serverSocket.accept();
                System.out.println("有新的客户端连接,端口号为:"+client.getPort());
                executorService.submit(new ExecuteClientRequest(client));
            }
            //关闭线程池与服务端
            executorService.shutdown();
            serverSocket.close();
        }
    }
    
  • 相关阅读:
    web页面常用方法及INI文件的读取方法
    winform 三个Panel左右切换(panel里面填充图片)
    图片渐出轮播的效果
    Winform跑马灯——Graphics运用
    .net 3.5 新功能重写ToInt()方法
    style.display
    SQL: 分页SQL SQL2005函数分页!
    JS: 验证输入必须为数字
    Table 里面点标题会进行排序
    在Div中绑定数据
  • 原文地址:https://www.cnblogs.com/impw/p/15456271.html
Copyright © 2011-2022 走看看