監聽TCP端口號:從簡單Socket到NIO到Netty


一、思路

1. 監聽端口:在服務器端創建一個ServerSocket對象,去監聽某個端口

2. 創建連接:通過serverSocket.accept() 創建一個Socket對象,等待客戶端連接,當有客戶端連接到這個端口,Socket對象就創建成功

3. 接收消息:client.getInputStream() 阻塞式接收客戶端往這個端口發送的消息

 

二、簡單代碼實現

public static void main(String[] args) throws IOException {

        int port = 8234;

        // 1. 創建ServerSocket對象,去監聽端口號
        try (ServerSocket serverSocket = new ServerSocket(port)) {

            System.out.println("啟動程序監聽8234端口...");

            Socket client = null;

            Boolean flag = true;

            while (flag) {
                // 2. 創建Socket對象去等待客戶端連接
                client = serverSocket.accept();
                System.out.println("客戶端" + client.getInetAddress().getHostAddress() + "連接到服務器...");

                // 3. 當客戶端連接上之后,創建一個線程去處理這個客戶端發送的數據,然后等待下一個客戶端的連接
                new Thread(new ProcessDataThread(client)).start();
            }

            client.close();
            System.out.println("服務器關閉");
        }
    }
public class ProcessDataThread implements Runnable {

    private Socket client;

    public ProcessDataThread(Socket socket) {
        this.client = socket;
    }

    @Override
    public void run() {
        try {
            // 1. 獲取客戶端發送過來的消息,此時是通過二進制流獲取,也可以用InputStreamReader通過字符串接收
            try (InputStream in = client.getInputStream()) {
                byte[] buffer = new byte[1024];
                while ((in.read(buffer)) != -1) {
                    try {
                        // 2. 處理數據,如果處理發生異常,不影響下次接收數據
                    } catch (Exception ex) {
                        System.out.println("處理數據發生異常:" + ex);
                    }
                }
            }
        } catch (Exception ex) {
            System.out.println("客戶端連接發生異常:" + ex);
        }
    }
}

 

 三、NIO優化,但強烈不建議使用Java原生的NIO

1. 單線程

2. 多線程優化,對應上面的代碼

3. 線程池優化

對於每一個請求,單獨開一個線程進行相應的邏輯處理,如果客戶端的數據傳遞是斷斷續續的,相應的線程需要I/O等待(有阻塞),並進行上線文切換(耗資源)

4. 使用NIO的Selector機制,提升程序並發效率

a. Channel用於連接和傳輸

b. Buffer 用於存儲

c. 用於管理請求

 

 

 

 

四、Netty優化

1. Netty是對NIO的進一步封裝

2. Netty代碼

<dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.6.Final</version>
</dependency>
public class NettyServer {
    public static void main(String[] args) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        NioEventLoopGroup boos = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        serverBootstrap
                .group(boos, worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    protected void initChannel(NioSocketChannel ch) {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                                System.out.println(msg);
                            }
                        });
                    }
                })
                .bind(8000);
    }
}
public class NettyClient {
    public static void main(String[] args) throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();

        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel ch) {
                        ch.pipeline().addLast(new StringEncoder());
                    }
                });

        Channel channel = bootstrap.connect("127.0.0.1", 8000).channel();

        while (true) {
            channel.writeAndFlush(new Date() + ": hello world!");
            Thread.sleep(2000);
        }
    }
}

 

 

 

參考:

https://blog.csdn.net/qq_36278071/article/details/79151422

https://www.cnblogs.com/snailclimb/p/9086334.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM