【Java EE 初阶】网络编程套接字TCP的实现

该文章展示了如何使用Java的ServerSocket和SocketAPI创建一个TCP回显服务器,并通过线程池(ThreadPoolExecutor)处理多个客户端连接,以避免为每个客户端创建新的线程导致的资源消耗。服务器代码中,当接收到客户端连接时,将其提交到线程池进行处理,每个连接都在单独的子线程中运行,提高了服务端的并发能力。
摘要由CSDN通过智能技术生成

目录

1.实现一个TCP的回显服务

1.Sever Socket API

1.SeverSocket 构造方法

2.Sever Socket方法

 2.Socket API

1.Socket的构造方法

2.Socket 方法

那么怎么实现让服务器可以处理多个客户端呢?

服务端代码:

客户端代码:


1.实现一个TCP的回显服务

1.Sever Socket API

Sever Socket 是创建TCP服务端Socket的API

1.SeverSocket 构造方法

2.Sever Socket方法

 2.Socket API

1.Socket的构造方法

2.Socket 方法

 

但是此服务器只能连接一个客户端,如果需要连接另一个客户端,只能让当前客户端断开连接,再连接另一个客户端

那么怎么实现让服务器可以处理多个客户端呢?

1.可以为每一个客户创建一个新的线程,让请求的处理在单独的子线程中去执行

但是这样如果有一万个客户端需要连接那就要创建一万个线程,会消耗非常大的系统资源,这时我们就可以通过线程池的方式进行优化,只给真正有需要的客户端建立连接

服务端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TCPEchoSever {

    private ServerSocket server;

    public TCPEchoSever(int port) throws IOException {
        if (port < 1025 || port > 65535) {
            throw new RuntimeException("端口号要在 1025 ~ 65535之间.");
        }
        //实例化SeverSocket对象
        this.server = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器已启动~~");

        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3,10,1, TimeUnit.SECONDS,new LinkedBlockingDeque<>(10));
        // 循环接收客户端的连接
        while (true) {
            //接收客户端的数据
            Socket clientSocket = server.accept();
            // 提交任务到线程池中
            poolExecutor.submit(() -> {
                try {
                    processConnections(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }

    }
    //处理数据
    private void processConnections(Socket clientSocket) throws IOException {
        // 打印日志
        String clientInfo = MessageFormat.format("[{0}:{1}] 客户端已上线", clientSocket.getInetAddress(),
                clientSocket.getPort());
        System.out.println(clientInfo);
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()){
            while (true) {
                Scanner requestScanner = new Scanner(inputStream);
                if (!requestScanner.hasNextLine()) {
                    // 日志
                    clientInfo = MessageFormat.format("[{0}:{1}] 客户端已下线.", clientSocket.getInetAddress(),
                            clientSocket.getPort());
                    System.out.println(clientInfo);
                    break;
                }
                String request = requestScanner.nextLine();
                String response = process(request);
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                printWriter.flush();
                // 打印日志
                clientInfo = MessageFormat.format("[{0}:{1}], request: {2}, response: {3}",
                        clientSocket.getInetAddress(), clientSocket.getPort(), request, response);
                System.out.println(clientInfo);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            clientSocket.close();
        }
    }

    private String  process(String request) {
        System.out.println("收到新消息:"  + request);
        Scanner scanner = new Scanner(System.in);
        String response = scanner.nextLine();
        return response;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoSever server = new TCPEchoSever(6666);
        server.start();
    }
}

 客户端代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TCPEchoClient {
    private Socket clientSocket;

    public TCPEchoClient (String serverIp, int serverPort) throws IOException, IOException {
        this.clientSocket = new Socket(serverIp, serverPort);
    }

    public void start() throws IOException {
        System.out.println("客户端已启动~~");
        // 获取Socket中的输入输出流
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            // 循环处理用户的输入
            while (true) {
                System.out.println("->");
                // 接收用户的输入内容
                Scanner requestScanner = new Scanner(System.in);
                String request = requestScanner.nextLine();
                // 发送用户的请求
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(request);
                // 强制刷新缓冲区
                printWriter.flush();
                // 接收服务器的响应
                Scanner responseScanner = new Scanner(inputStream);
                // 获取响应数据
                String response = responseScanner.nextLine();
                // 打印响应内容
                System.out.println("接收到服务器的响应:" + response);

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            clientSocket.close();
        }
    }

    public static void main(String[] args) throws IOException {
        TCPEchoClient client = new TCPEchoClient("127.0.0.1", 6666);
        client.start();
    }
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值