Socket编程实现一对一单独聊天

服务端代码

public class Server2dl {
    private ServerSocket severSocket;
    //存储所有客户端的输出流
    private Map<String,PrintWriter> allout;
    
    Server2dl(){
    try {
    //创建服务端的ServerSocket对象
        severSocket=new ServerSocket(8087);
        allout=new HashMap<String,PrintWriter>();
    } catch (IOException e) {
    // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
    //创建内部类,继承runnable的形式创建线程
        private class clientHandler implements Runnable{
        private Socket socket;
        String user;
        clientHandler(Socket socket){
            this.socket=socket;
    }
    @Override
    public void run() {
    // TODO Auto-generated method stub
    //获取向该客户端发送信息的输出流,并且将该流包装成PrintWriter之后
    //放入集合中,如果客户掉线,集合中对应的输出流从集合中删除
        PrintWriter pw=null;
        InputStream is;
        PrintWriter p1=null;
    
    try {
    //获取outputStream对象 获取socket中的输出流
        OutputStream os=socket.getOutputStream();
        //缓冲字符输出流
        OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
        pw=new PrintWriter(osw,true);
        //将用户信息放入集合当中
    
    //在获取到了客户端发送过来的信息后遍历集合allout
    //将获取到的信息写入该集合中每一个输出流中,从而将信息发送给所有的客户端
    //声明该线程被创建后要执行的任务
        is = socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is,"utf-8");
        BufferedReader br=new BufferedReader(isr);
        String message=null;
    //readLine只有在数据流发生异常,或者另一端被close()的时候返回null值
        while((message=br.readLine()) != null) {
        //遍历所有的输出流,将该客户端发送的信息转发给所有的用户
        String kf=message.substring(message.lastIndexOf("对")+1, message.lastIndexOf("说:"));
        //System.out.println(kf);
        user=message.substring(message.lastIndexOf("户")+1, message.lastIndexOf("对"));
        allout.put(user, pw);
        //System.out.println(allout);
        //System.out.println(kf);
        if(allout.get(kf)==null) {
            pw.println("该用户还未连接");
            }
            if(allout.get(kf)!=null) {
            p1=allout.get(kf);
            pw.println(message);
            p1.println(message);
            }
            System.out.println(message);
            }
            } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }finally {
            //当客户掉线的时候,要将输出流从集合删除
            allout.remove(user);
            if(socket!=null) {
            try {
            socket.close();
            } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }
            }
        
        }
    
    
        }
    
        }
    
        public void start() {
        System.out.println("等待客户端的连接");
        //监听客户端的连接
        Socket socket;
            try {
                while(true) {
        //连接客户端的socket的对象
                    socket = severSocket.accept();
                    System.out.println("客户端已连接");
        //启动线程来完成针对该客户端的交互 因为accept()有阻塞的功能
        //accept()方法会产生阻塞,直到某个Socket连接,并返回请求连接的socket
        //所以程序在 多人访问时必须用线程并发执行
                    Thread t=new Thread(new clientHandler(socket));
                    t.start();
                }    
        } catch (IOException e) {
        // TODO Auto-generated catch block
            e.printStackTrace();
            }
        
        
        
        }
            public static void main(String[] args) {
            Server2dl server=new Server2dl();
            server.start();
        }

}

客户端代码:

//客户端应用程序
        //第一步:实现向服务器发送一条信息
        public class Client2dl {
        //创建Socket实例
        private    Socket socket;
        public Client2dl() {
            try {
        //创建socket连接
                socket=new Socket("localhost",8087);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        }
        
        
        //客户端工作方法
        public void start() {
        Scanner sc=null;
            try {
        //接收服务器端的信息并且启动线程
                ServerHander handler=new ServerHander();
                    Thread r=new Thread(handler);
                    r.start();
                    //获取outputStream对象 获取socket中的输出流
                    OutputStream os=socket.getOutputStream();
        //缓冲字符输出流
                    OutputStreamWriter osw=new OutputStreamWriter(os,"utf-8");
                    PrintWriter out=new PrintWriter(osw,true);
                    //创建Scanner类读取用户输入内容
                    System.out.println("请输入你的用户名:");
                    sc=new Scanner(System.in);
                    String user=sc.nextLine();
                    System.out.println("请输入你想和谁聊:");
                    sc=new Scanner(System.in);
                    String say=sc.nextLine();
                    System.out.println("输入您的聊天内容");
                    sc=new Scanner(System.in);
        //将信息 发送给服务器
        while(true) {
        out.println("用户"+user+"对"+say+"说:"+sc.nextLine());    
        }
        
        
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }finally {
            try {
            if(socket!=null) {
            socket.close();
            }
            
            } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            }    
            }
            }
        
        private class ServerHander implements Runnable{
        
        @Override
        public void run() {
        InputStream is;
        // TODO Auto-generated method stub
        //接收服务端发送的信息
        //循环接收并显示
        try {
        is = socket.getInputStream();
        InputStreamReader isr=new InputStreamReader(is,"utf-8");
        BufferedReader br=new BufferedReader(isr);
        while(true) {
        System.out.println(br.readLine());
        }
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
        
        }
        
        }
        //创建main方法
        public static void main(String[] args) {
        Client2dl c=new Client2dl();
        c.start();
        }
        
        }

PS:先运行服务端,后运行客户端.

猜你喜欢

转载自blog.csdn.net/CXY_ZPH/article/details/86530752