简介

  • 本文主要使用Java.net包下的Socket与ServerSocket实现一个简单的单服务端与多客户端之间的通信,该通信模型为BIO模型,且不进行SSL/TLS通信加密。

  • 在本项目中,服务端采用线程池维护一定数量的线程,用以保持与客户端间的通信。

主要代码

服务端

服务端主线程 Server.java

  • 该部分维护一个线程池,线程池的参数由CORE_POOL_SIZE,MAXIMUM_POOL_SIZE,KEEP_ALIVE_TIME给出,并新建一个ServerSocket,在main线程中监听ServerSocket,获取新的Socket连接,并创建业务线程。
serverSocket = new ServerSocket(PORT);

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
        MAXIMUM_POOL_SIZE,
        KEEP_ALIVE_TIME,
        TimeUnit.SECONDS,
        new LinkedBlockingQueue<Runnable>());

while (true){
    Socket socket = serverSocket.accept();
    System.out.println("Server accept a socket.");
    threadPoolExecutor.execute(new ServerTask(socket));
}

服务端业务线程 ServerTask.java

  • 该线程获取socket的输入输出流,为了方便演示,下列仅实现输入流的读取。对于InputStream与OutputStream的多线程读取不做实现。
  • 下列线程中,读取InputStream中的内容,并在控制台输出客户端的相关信息。
private static final int BUFFER_SIZE = 1024;

private Socket serverSocket;

public ServerTask(Socket socket){
    this.serverSocket = socket;
}

public void run() {
    try {
        InputStream in = serverSocket.getInputStream();
        OutputStream out = serverSocket.getOutputStream();
        byte[] data=null;
        while (serverSocket.isConnected()){
            data = new byte[BUFFER_SIZE];
            String resultData = new String(data);
            if (in.read(data,0,BUFFER_SIZE) > -1){
                System.out.println("Server Receives Message from port: "
                        + serverSocket.getInetAddress().getHostAddress() + ":"
                        + serverSocket.getPort());
                System.out.println(new String(data, Charset.forName("UTF-8")));
                System.out.println("Receive Time:" + System.currentTimeMillis());
            }

        }
    }catch (IOException ex){
        ex.printStackTrace();
    }finally {
        try {
            serverSocket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

客户端

客户端线程 ClientTask.java

  • 该线程主要用于新建与目标服务端的Socket连接,并间隔2s向OutputStream进行写入
private static final String HOST = "127.0.0.1";
private static final int PORT = 8080;

private Socket socket;
private String clientName;

public ClientTask(String name){
    this.clientName = name;
    socket = new Socket();
    try {
        socket.connect(new InetSocketAddress(HOST,PORT),60);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {
    try {
        OutputStream out = socket.getOutputStream();
        while (true){
            String transferData = "Client " + clientName + " heart beat.";
            System.out.println(transferData);
            out.write(transferData.getBytes(Charset.forName("UTF-8")));
            System.out.println("Transfer Time: " + System.currentTimeMillis());
            Thread.sleep(2000);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

创建客户端

  • 该步可通过新建客户端线程ClientTask.java并运行,该部分实现方法有多种,下面提供一个简单实现
public static void main(String[] args){
    new Thread(new ClientTask("Client_01")).run();
}

运行结果示例

  • 服务端运行结果
    QQ截图20210603171592.png
  • 客户端运行结果
    QQ截图20210603171591.png

标签: Java, Socket

评论已关闭