赞
踩
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(); } }
这里就不再赘述!
下面写一下理论性的东西:
先从Socket讲起:
Socket,又称为套接字,用于描述 IP 地址和端口。应用程序通常通过 socket向网络发出请求或者应答网络请求。Socket 就是为网络编程提供的一种机制:
通信两端都有 socket;
网络通信其实就是 socket 之间的通信;
数据在两个 socket 之间通过 IO 传输。
网络编程也称作为 Socket 编程,套接字编程。
Socket 通信是 Client/Server 模型
而网络通信的本质是网络间的数据 IO,这又牵扯出了 BIO 和 NIO这两个通讯模型:
只要有 IO,就会有阻塞或非阻塞的问题,无论这个 IO 是网络的,还是硬盘的。原因在于程序是运行在系统之上的,任何形式的IO 操作发起都需要系统内核的支持。
BIO 即 blocking IO,是一种阻塞式的 IO。
jdk1.4 版本之前 Socket 即 BIO 模式。
BIO 的问题在于 accept()、read()的操作点都是被阻塞的。
服务器线程发起一个 accept 动作,询问操作系统是否有新的 socket 信息从端口 X 发送过来。注意,是询问操作系统。如果操作系统没有发现有 socket 从指定的端口X 来,那么操作系统就会等待。这样 serverSocket.accept()方法就会一直等待。这就是为什么 accept()方法为什么会阻塞。
如果想让 BIO 同时处理多个客户端请求,就必须使用多线程,即每次 accept阻塞等待来自客户端请求,一旦收到连接请求就建立通信,同时开启一个新的线程来处理这个套接字的数据读写请求,然后立刻又继续 accept 等待其他客户端连接请求,即为每一个客户端连接请求都创建一个线程来单独处理。
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是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。Netty相当简化和流线化了网络应用的编程开发过程,例如,TCP和UDP的socket服务开发。
“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议的实现经验,这些协议包括FTP,SMTP,HTTP,各种二进制,文本协议,并经过相当精心设计的项目,最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性
Socket的客户端也可以由Netty实现,但是使用Socket直接实现客户端,而服务端由Netty实现,这样可以更好的理解Netty!
完!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。