Socket实现聊天客户端

本文通过一个实战案例介绍了如何使用Socket进行客户端和服务端通信。在服务端采用多线程处理客户端请求,利用ServerSocket监听客户端连接,并将连接信息存入队列以便广播消息。客户端通过telnet进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在极客学院上看到了一个关于Socket的视频讲解,感觉还不错,就写了份代码,拿来分享一下。


Socket使用方法

关于Socket的使用,我们首先要弄清楚的是,在服务器端还是在客户端使用。因为这的确是很重要的。

  • 对于客户端,需要使用new Socket(ip,port)就可以了。

  • 对于服务器端的话,我们需要借助于ServerSocket 的accept方法获得与特定的客户端相关联的Socket实例。

  • 然后通信的双方借助于socket里面的方法,获得输出流和输入流完成相关的通信的逻辑处理就可以了


我的服务器端的实现

首先先展示一下我的目录结构吧。

这里写图片描述
每个类的实现的功能就是:

  • ChatManager:添加socket到队列;发送数据
  • ChatSocket: 实现了单独的线程的通信处理
  • MainTest: 本类的测试入口
  • ServerListener: 服务器端的侦听类,负责获取连接成功的客户端

然后是具体的代码。
个人建议代码的阅读顺序为:MainTest.java–>ServerListener.java–>ChatSocket.java–> ChatManager.java


package com.mark.chatserver;

import java.util.Vector;

/**
 * 通信客户端管理类
 * 实现的业务就是将产生的客户端添加到服务器端的一个队列中
 * 并把所有客户端产生的信息,发送给所有的客户端对象
 * @author lhdn
 *
 */
public class ChatManager {

    private ChatManager(){}
    private static final ChatManager newInstance = new ChatManager();
    public static Vector<ChatSocket> vector = new Vector<ChatSocket>();


    public static ChatManager getChatManager() {

        return newInstance;
    }

    /**
     * 添加一个客户端到队列中
     * @param cm
     */
    public void add(ChatSocket cm ){
        vector.add(cm);
    }


    /**
     * 发布客户端的消息
     * @param chatSocket
     * @param line
     */
    public void publish(ChatSocket chatSocket, String line) {
        for(int i = 0 ; i< vector.size() ;i++) {
            ChatSocket temp = (ChatSocket) vector.get(i);
            //过滤自身发送给服务器端的信息
            if(!temp.equals(chatSocket)){
                temp.out(line);
            }
        }

    }

}
package com.mark.chatserver;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

/**
 * 用来和客户端进行通信的线程类
 * @author lhdn
 *
 */
public class ChatSocket extends Thread {

    private Socket socket ;

    public ChatSocket(Socket s) {
        this.socket = s;
    }

    /**
     * 向客户端输出信息(以字节的方式)
     * @param str
     */
    public void out(String str) {
        try {
            OutputStream os = socket.getOutputStream();
            os.write((str+"\n").getBytes("UTF-8"));
            os.flush();
        } catch (Exception e) {
            throw new RuntimeException("没有向客户端输出正确的信息");
        }
    }

    @Override
    public void run() {
        out("\n恭喜,您已经连接到了我们的服务器了!\n");
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
            String line = "";
            while((line = reader.readLine())!=null) {
                System.out.println(line);
                ChatManager.getChatManager().publish(this,line);
            }
        } catch (Exception e) {
            // TODO: handle exception
        }
    }


}
package com.mark.chatserver;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javax.swing.JOptionPane;

/**
 * 主要的框架类,用于侦听客户端的链接并将服务器端产生的socket以一个新的线程的方式进行运行
 * @author lhdn
 *
 */
public class ServerListener extends Thread {

    @Override
    public void run() {
        try {
            ServerSocket server = new ServerSocket(9999);
            while(true){
                Socket socket = server.accept();
                JOptionPane.showMessageDialog(null, "现在有客户端连接上了服务器!");
                ChatSocket chatSocket = new ChatSocket(socket);
                chatSocket.start();
                ChatManager.getChatManager().add(chatSocket);
            }
        } catch (IOException e) {
            // TODO: handle exception
        }

    }

}
package com.mark.chatserver;

public class MainTest {

    public static void main(String []args){
        ServerListener serverListener = new ServerListener();
        serverListener.start();
    }

}

下面一起来看一下代码的测试效果吧

这里使用到的是XUbuntu终端telnet方式


这里写图片描述

这里写图片描述


总结

这个小程序的核心的思想就在于使用线程来进行客户端的信息的处理。
再来回顾一下整个服务器端的原理和流程吧。
*-* 1首先创建出一个ServerSocket对象来侦听来自于客户端的链接

*-* 2将链接到的客户端对应的Socket添加到一个队列中(这里使用了一个单独的类ChatManager进行了实现),并开启这个新的线程进行处通信

*-* 3使用相关的输入流,输出流进行数据的交互

*-* 4使用终端的telnet的方式实现了服务器端的测试,对于从事后台开发的很方便哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值