Java面试知识点(七十一)Socket编程进阶——简易聊天室

154 篇文章 5 订阅
150 篇文章 6 订阅

之前介绍了 socket基础编程Java面试知识点(七十)Socket编程——C/S架构基础入门 ,包括单客户端和多客户端的情况,现在在说一下其他情况

简易聊天室

跟之前的多客户端的情况一样,也是需要多线程来保持多个连接,但是额外要引入一个线程池,需要服务器记录所有的连接客户端,这样一个客户端发送信息之后,就可以把这个信息发送给其他保持连接的客户端,代码如下:

【子线程服务类】

package test.socket.chatroom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

/**
 * 单一服务器线程类
 * 可以实现跟与当前线程服务器的连接的客户端的信息通讯
 * 同时还保存着当前服务器的全部连接的线程,以便实现发送给其他客户端信息
 * */
public class SingleServer implements Runnable {
    // 创建线程连接池,存储线程名和线程
    private Map<String,Socket> pool;
    // 创建socket
    private Socket socket;
    private String name;

    public SingleServer(Map<String,Socket> pool, String name,Socket socket) {
        this.pool = pool;
        this.socket = socket;
        this.name = name;
        // 将socket线程加入线程池中
        this.pool.put(this.name,this.socket);
    }

    @Override
    public void run() {
        read();
    }

    // 获取当前线程的客户端的信息
    private void read() {
        try {
            boolean flag = true;
            while (flag) {
                BufferedReader reader =
                        new BufferedReader(new InputStreamReader(socket.getInputStream()));
                if (reader.ready()) {
                    String str = reader.readLine();
                    // 服务器获得之后可以保存在本地当做日志,这里简单打印
                    System.out.println(name+"客户端: "+str);
                    // 把接收到的信息发送给其他客户端并打印
                    Iterator it = pool.keySet().iterator();
                    while (it.hasNext()) {
                        String key = (String)it.next();
                        if (this.socket != pool.get(key)) {
                            write(pool.get(key),name+"客户端: "+str);
                        }
                    }

                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 把信息发送到客户端
     * */
    private void write(Socket socket, String str) {
        try {
            PrintWriter writer
                    = new PrintWriter(socket.getOutputStream(),true);
            writer.println(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【服务器类】

package test.socket.chatroom;

import test.test.thread1;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class Server {
    public static void main(String[] args) {
        try {
            // 监听端口
            ServerSocket server = new ServerSocket(9999);
            // 线程池
            Map<String, Socket> pool = new HashMap<>();

            System.out.println("服务器启动...");

            int i = 0;
            // 循环侦听
            while (true) {
                // 客户端id
                i++;
                String id = i+ "";
                // 开启线程
                SingleServer singleServer = new SingleServer(pool,id,server.accept());
                Thread thread = new Thread(singleServer);
                thread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【客户端类】

package test.socket.chatroom;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
    public static void main(String[] args) {
        // 建立连接
        try {
            Socket socket = new Socket("localhost",9999);
            System.out.println("客户端启动");
            while (true) {
                // 读取信息
                BufferedReader reader
                        = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                if (reader.ready()) {
                    String str = reader.readLine();
                    System.out.println(str);
                }

                // 写信息
                PrintWriter writer =
                        new PrintWriter(socket.getOutputStream(),true);
                BufferedReader key =
                        new BufferedReader(new InputStreamReader(System.in));
                if (key.ready()) {
                    String str = key.readLine();
                    writer.println(str);
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【运行结果】
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
后期还可以加上发送时间,左右分区,加上身份验证等等


还有一些问题,服务器无法发送给全部客户端信息
待续…

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java Socket编程可以用于实现多人聊天室。以下是一个简单的Java多人聊天室的代码示例: Server端代码: ```java import java.io.*; import java.net.*; import java.util.*; public class Server { ArrayList<PrintWriter> clientOutputStreams; public class ClientHandler implements Runnable { BufferedReader reader; Socket socket; public ClientHandler(Socket clientSocket) { try { socket = clientSocket; InputStreamReader isReader = new InputStreamReader(socket.getInputStream()); reader = new BufferedReader(isReader); } catch (Exception ex) { ex.printStackTrace(); } } public void run() { String message; try { while ((message = reader.readLine()) != null) { System.out.println("read " + message); tellEveryone(message); } } catch (Exception ex) { ex.printStackTrace(); } } } public static void main (String[] args) { new Server().go(); } public void go() { clientOutputStreams = new ArrayList<PrintWriter>(); try { ServerSocket serverSock = new ServerSocket(5000); while(true) { Socket clientSocket = serverSock.accept(); PrintWriter writer = new PrintWriter(clientSocket.getOutputStream()); clientOutputStreams.add(writer); Thread t = new Thread(new ClientHandler(clientSocket)); t.start(); System.out.println("got a connection"); } } catch (Exception ex) { ex.printStackTrace(); } } public void tellEveryone(String message) { Iterator<PrintWriter> it = clientOutputStreams.iterator(); while (it.hasNext()) { try { PrintWriter writer = (PrintWriter) it.next(); writer.println(message); writer.flush(); } catch (Exception ex) { ex.printStackTrace(); } } } } ``` Client端代码: ```java import java.io.*; import java.net.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Client { JTextArea incoming; JTextField outgoing; BufferedReader reader; PrintWriter writer; Socket sock; public static void main(String[] args) { new Client().go(); } public void go() { JFrame frame = new JFrame("Ludicrously Simple Chat Client"); JPanel mainPanel = new JPanel(); incoming = new JTextArea(15,50); incoming.setLineWrap(true); incoming.setWrapStyleWord(true); incoming.setEditable(false); JScrollPane qScroller = new JScrollPane(incoming); qScroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); qScroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); outgoing = new JTextField(20); JButton sendButton = new JButton("Send"); sendButton.addActionListener(new SendButtonListener()); mainPanel.add(qScroller); mainPanel.add(outgoing); mainPanel.add(sendButton); setUpNetworking(); Thread readerThread = new Thread(new IncomingReader()); readerThread.start(); frame.getContentPane().add(BorderLayout.CENTER, mainPanel); frame.setSize(400,500); frame.setVisible(true); } private void setUpNetworking() { try { sock = new Socket("127.0.0.1", 5000); InputStreamReader streamReader = new InputStreamReader(sock.getInputStream()); reader = new BufferedReader(streamReader); writer = new PrintWriter(sock.getOutputStream()); System.out.println("networking established"); } catch (IOException ex) { ex.printStackTrace(); } } public class SendButtonListener implements ActionListener { public void actionPerformed(ActionEvent ev) { try { writer.println(outgoing.getText()); writer.flush(); } catch (Exception ex) { ex.printStackTrace(); } outgoing.setText(""); outgoing.requestFocus(); } } public class IncomingReader implements Runnable { public void run() { String message; try { while ((message = reader.readLine()) != null) { System.out.println("client read " + message); incoming.append(message + "\n"); } } catch (Exception ex) { ex.printStackTrace(); } } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值