SpringBoot实现Socket客户端,Netty服务端实现Java通讯(附源码及注释详解)

SpringBoot实现Socket通讯:
使用Netty实现一个Socket通讯,包括客户端和服务端,通过服务端进行监听,客户端发送信息,服务端可进行接收,并进行返回数据,完成一个完整的通讯
客户端用的Socket编程,而服务端用到Netty框架实现。源码地址:

源码地址!!!!!!!!

而且启动初始化及调用的日志、注释写的很清楚,如下:

package com.xu.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * soket监听服务
 * 
 * @author xu
 */
public class NettyServer implements Runnable {

    /** 异常输出 */
    private static final Logger LOGGER = LoggerFactory.getLogger(NettyServer.class);

    /**
     * soket监听
     */
    public static void soketListener() {
    	LOGGER.info("================5.NettyServer开始启动========================");
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        int port = 58765;
        try {
        	LOGGER.info("================7.1 NettyServer 端口为:" + port + "========================");
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)  //绑定线程池
                .channel(NioServerSocketChannel.class)  // 指定使用的channel
                .childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 65535, 65535))
                .childHandler(new ChannelInitializer<SocketChannel>() { // 绑定客户端连接时候触发操作

                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    LOGGER.info("================7.2 报告,有个socket客户端链接到本服务器, IP为:" + ch.localAddress().getHostName() + ", Port为:" + ch.localAddress().getPort() + "========================");
                    ch.pipeline().addLast(new ServerHandler()); // 客户端触发操作
                }
            });
            LOGGER.info("================8.NettyServer 启动中.....========================");
            ChannelFuture channelFuture = bootstrap.bind(port).sync(); // 服务器异步创建绑定
            LOGGER.info("================9.NettyServer 启动完毕!!========================");
            channelFuture.channel().closeFuture().sync(); // 关闭服务器通道
            LOGGER.info("================41.NettyServer 关闭服务器通道!!========================");
        } catch (Exception e) {
        	LOGGER.error("================4.1 NettyServer 端口为:" + port + " 启动出现异常, 异常内容为:" + e.getMessage() + "========================");
        } finally {
        	LOGGER.error("================4.2 NettyServer 服务关闭========================");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    /**
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        LOGGER.info("================4.多线程启动Netty Server========================");
        NettyServer.soketListener();
    }

}

这里就不再赘述!

下面写一下理论性的东西:

Netty很强大: 阿里的Dubbo的底层就是用的Netty

先从Socket讲起:

1. Socket 机制

Socket,又称为套接字,用于描述 IP 地址和端口。应用程序通常通过 socket向网络发出请求或者应答网络请求。Socket 就是为网络编程提供的一种机制:
通信两端都有 socket;
网络通信其实就是 socket 之间的通信;
数据在两个 socket 之间通过 IO 传输。
网络编程也称作为 Socket 编程,套接字编程。
Socket 通信是 Client/Server 模型

而网络通信的本质是网络间的数据 IO,这又牵扯出了 BIO 和 NIO这两个通讯模型:

2. IO通讯模型

只要有 IO,就会有阻塞或非阻塞的问题,无论这个 IO 是网络的,还是硬盘的。原因在于程序是运行在系统之上的,任何形式的IO 操作发起都需要系统内核的支持。

在这里插入图片描述

2.1 BIO(阻塞模式)

BIO 即 blocking IO,是一种阻塞式的 IO。
jdk1.4 版本之前 Socket 即 BIO 模式。
BIO 的问题在于 accept()、read()的操作点都是被阻塞的。
服务器线程发起一个 accept 动作,询问操作系统是否有新的 socket 信息从端口 X 发送过来。注意,是询问操作系统。如果操作系统没有发现有 socket 从指定的端口X 来,那么操作系统就会等待。这样 serverSocket.accept()方法就会一直等待。这就是为什么 accept()方法为什么会阻塞。
如果想让 BIO 同时处理多个客户端请求,就必须使用多线程,即每次 accept阻塞等待来自客户端请求,一旦收到连接请求就建立通信,同时开启一个新的线程来处理这个套接字的数据读写请求,然后立刻又继续 accept 等待其他客户端连接请求,即为每一个客户端连接请求都创建一个线程来单独处理。
在这里插入图片描述

扫描二维码关注公众号,回复: 10863089 查看本文章

2.2 NIO(非阻塞模式)

NIO 即 non-blocking IO,是一种非阻塞式的 IO。jdk1.4 之后提供。
NIO 三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器)。 Buffer:容器对象,包含一些要写入或者读出的数据。在 NIO 库,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的;在写入数据时,也是写入到缓冲区中。任何时候访问 NIO 中的数据,都是通过缓冲区进行操作。
Channel:通道对象,对数据的读取和写入要通过 Channel,它就像水管一样。通道不同于流的地方就是通道是双向的,可以用于读、写和同时读写操作。 Channel不会直接处理字节数据,而是通过 Buffer 对象来处理数据。
Selector:多路复用器,选择器。提供选择已经就绪的任务的能力。Selector会不断轮询注册在其上的 Channel,如果某个 Channel 上面发生读或者写事件,这个Channel 就处于就绪状态,会被 Selector 轮询出来,进行后续的 I/O 操作。这样服务器只需要一两个线程就可以进行多客户端通信。

在这里插入图片描述
在这里插入图片描述

而Netty就是使用的NIO,这也是Netty框架高性能的原因!!

Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。

“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性

Socket的客户端也可以由Netty实现,但是使用Socket直接实现客户端,而服务端由Netty实现,这样可以更好的理解Netty!

完!!

发布了107 篇原创文章 · 获赞 20 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/beishanyingluo/article/details/101478887