TCP服务器

可选的TCP服务器有Mina、Netty、Twisted等,它们都是异步、事件驱动(asynchronous、event-driven)的网络编程框架。
其中MINA和Netty是基于Java语言的,Twisted是Python语言的。语言不是重点,重点的是理念。

  • 传统的BIO(Blocking IO/阻塞IO)进行网络编程时,进行网络IO读写时都会阻塞当前线程,使用BIO实现一个TCP服务器,需要对每个客户端连接开启一个线程,很多线程可能会阻塞住等待读写数据,系统资源消耗大。
  • NIO(Non-Blocking IO/非阻塞IO)或AIO(Asynchronous IO/异步IO)通过IO多路复用技术实现,不需要为每个连接创建一个线程,其底层实现使用了操作系统的一些特性如select、pool、epoll、iocp等。

Mina、Netty、Twisted一起学(一):实现简单的TCP服务器
Netty 4.x 用户指南
Netty in Action 学习
一起学Netty
netty(一) java NIO

同步阻塞I/O

Java的两个IO方法 read和write都是同步阻塞的。
阻塞指的是read和write都会阻塞线程直到读取或发送完成或异常。
同步指的是发送方和接收方是同步的,缓慢的发送和网络传输会使接收长时间阻塞,缓慢的接收和网络传输和狭小的TCP缓冲区也会使发送长时间阻塞,所以发送和接收的速度互相影响。
输入流和输出流的读和写操作都是同步阻塞的,阻塞的时间取决于对方I/O线程的处理速度和网络I/O的传输速度。

Java NIO

JDK1.4引入了新的输入/输出(NIO)库。相比jdk1.3,NIO弥补了原来同步阻塞I/O的不足,提供了高速的、面向块的I/O。
一些NIO新增的类库和概念:
1.缓冲区Buffer
在面向流的I/O中,可以将数据直接写入或读到Stream对象中。
在NIO库中,数据读写都是要经过缓冲区。缓冲区实质上是一个数组,并且一个缓冲区不仅仅是一个数组,它还提供了对数据的结构化访问以及维护读写位置(limit)等信息。
最常用的缓冲区是ByteBuffer,一个ByteBuffer提供了一组功能用于操作byte数组。包括ByteBuffer,每一种java基本类型(除了Boolean类型)都对应一种缓冲区:
ByteBuffer:字节缓冲区
CharBuffer:字符缓冲区
ShortBuffer:短整型缓冲区
IntBuffer:整形缓冲区
LongBuffer:长整型缓冲区
FloadBuffer:浮点型缓冲区
DoubleBuffer:双精度浮点型缓冲区
2.通道Channel
通道与流的不同之处在于通道是双向的,可以用于读、写或者二者同时进行,流只是在一个方向上移动(一个流必须是InputStream或者OutputStream的子类)。
因为Channnel是双全工的,所以它可以比流更好地映射底层操作系统的API。在UNIX网络编程模型中,底层操作系统的通道都是双全工的,同时支持读写操作。
实际上Channel可以分为两大类:用于网络读写的SelectbleChannel和用于文件操作的FileChannel。
与Socket类和ServerSocket类相对应,NIO提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现,它们都是SelectableChannel的子类,都支持阻塞和非阻塞两种模式。
3.多路复用器Selector
多路复用器提供选择已经就绪的任务的能力。Selector会不断地轮询注册在其上的Channel,如果某个Channel上面发生读写事件,这个Channel就处于了就绪状态,处于了就绪状态的Channel会被Selector轮询出来,然后通过SelectionKey可以读取就绪Channel集合,进行后续的I/O操作。
JDK在Linux等主流操作系统上通过epoll实现,所以它并没有最大连接句柄1024/2048的限制。这意味着只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。
Reactor反应器模式:使用单线程模拟多线程,提高资源的利用率和程序的效率,增加系统吞吐量。
Selector类似一个观察者,我们把需要探知的socketchannel告诉Selector,当有事件发生时,Selector会通知我们并传回一组SelectionKey,我们读取这些Key,会获得注册过的socketchannel,然后从这个Channel中读取数据。即主程序不用主动阻塞的等待数据,而是被通知有数据就绪。
4.AIO
JDK1.7升级了NIO类库,升级后的NIO类库被成为NIO2.0,正式提供了异步文件I/O操作,同时提供了与UNIX网络编程事件驱动I/O对应的AIO。NIO2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。异步通道提供以下两种方式获取操作结果。
(1)通过java.util.concurrent.Future类来表示异步操作的结果;
(2)在异步操作的时候传入一个java.nio.channels.CompletionHandler接口的实现类作为操作完成的回调。
NIO2.0的异步套接字通道是真正的异步非阻塞I/O,对应了UNIX网络编程中的事件驱动I/O(AIO),它不需要通过多路复用器(selector)对注册的通道进行轮询操作即可实现异步读写,从而简化了NIO的编程模型。

Base 128 Varints

Google Protobuf3

Google Protobuf 官方文档之Language Guide (proto3)
http://blog.163.com/lnsjc321@126/blog/static/5348428720154325730234/
https://developers.google.com/protocol-buffers/docs/proto3

Netty

LengthFieldBasedFrameDecoder 构造参数:

  • lengthFieldOffset:用于指示长度字段,设置为长度字段在整个数据包中开始的位置。
  • lengthFieldLength:用于指示长度字段,设置为长度字段占用的字节数。
  • lengthAdjustment:用于指示内容字段长度,表示在整个数据包长度的基础上,内容字段的长度的调节值。要小于等于0。
  • initialBytesToStrip:用于指示内容字段长度,设置为内容字段在整个数据包中开始的位置。

如果测试发送数据后,但总收不到响应数据。可能是上述参数没有配置对。
https://blog.csdn.net/thinking_fioa/article/details/80573483

发表评论