Mina、Netty、Twisted一起学:实现简单的TCP服务器

标签: mina netty twisted | 发表时间:2014-08-15 18:53 | 作者:xiao__gui
出处:http://blog.csdn.net

MINA、Netty、Twisted为什么放在一起学习?首先,不妨先看一下他们官方网站对其的介绍:

MINA:

Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract event-driven asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.

Netty:

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.

Twisted:

Twisted is an event-driven networking engine written in Python and licensed under the open source MIT license.

(Twisted官网的文案不专业啊,居然不写asynchronous)

从上面简短的介绍中,就可以发现它们的共同特点:event-driven以及asynchronous。它们都是 事件驱动、异步的网络编程框架。由此可见,它们之间的共同点还是很明显的。所以我这里将这三个框架放在一起,实现相同的功能,不但可以用少量的精力学三样东西,而且还可以对它们之间进行各方面的对比。

其中MINA和Netty是基于Java语言的,而Twisted是Python语言的。不过语言不是重点,重点的是理念。

使用传统的BIO(Blocking IO/阻塞IO)进行网络编程时,进行网络IO读写时都会阻塞当前线程,如果实现一个TCP服务器,都需要对每个客户端连接开启一个线程,而很多线程可能都在傻傻的阻塞住等待读写数据,系统资源消耗大。

而NIO(Non-Blocking IO/非阻塞IO)或AIO(Asynchronous IO/异步IO)则是通过IO多路复用技术实现,不需要为每个连接创建一个线程,其底层实现是通过操作系统的一些特性如select、pool、epoll、iocp等,这些都不是本文的重点。这三个网络框架都是基于此实现。

下面分别用这三个框架实现一个最简单的TCP服务器。当接受到客户端发过来的字符串后,向客户端回写一个字符串作为响应。

Mina:

public class TcpServer {

	public static void main(String[] args) throws IOException {
		IoAcceptor acceptor = new NioSocketAcceptor();
		acceptor.setHandler(new TcpServerHandle());
		acceptor.bind(new InetSocketAddress(8080));
	}

}

class TcpServerHandle extends IoHandlerAdapter {
	
	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		cause.printStackTrace();
	}

	// 接收到新的数据
	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		
		// 接收客户端的数据
		IoBuffer ioBuffer = (IoBuffer) message;
		byte[] byteArray = new byte[ioBuffer.limit()];
		ioBuffer.get(byteArray, 0, ioBuffer.limit());
		System.out.println("messageReceived:" + new String(byteArray, "UTF-8"));
		
		// 发送到客户端
		byte[] responseByteArray = "你好".getBytes("UTF-8");
		IoBuffer responseIoBuffer = IoBuffer.allocate(responseByteArray.length);
		responseIoBuffer.put(responseByteArray);
		responseIoBuffer.flip();
		session.write(responseIoBuffer);
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		System.out.println("sessionCreated");
	}
	
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		System.out.println("sessionClosed");
	}
}

Netty:

public class TcpServer {

	public static void main(String[] args) throws InterruptedException {
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.group(bossGroup, workerGroup)
					.channel(NioServerSocketChannel.class)
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						public void initChannel(SocketChannel ch)
								throws Exception {
							ch.pipeline().addLast(new TcpServerHandler());
						}
					}).option(ChannelOption.SO_BACKLOG, 128)
					.childOption(ChannelOption.SO_KEEPALIVE, true);
			ChannelFuture f = b.bind(8080).sync();
			f.channel().closeFuture().sync();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}

}

class TcpServerHandler extends ChannelInboundHandlerAdapter {

	// 接收到新的数据
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {
		try {
			// 接收客户端的数据
			ByteBuf in = (ByteBuf) msg;
			System.out.println("channelRead:" + in.toString(CharsetUtil.UTF_8));
			
			// 发送到客户端
			byte[] responseByteArray = "你好".getBytes("UTF-8");
			ByteBuf out = ctx.alloc().buffer(responseByteArray.length);
			out.writeBytes(responseByteArray);
			ctx.writeAndFlush(out);
			
		} finally {
			ReferenceCountUtil.release(msg);
		}
	}
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) {
		System.out.println("channelActive");
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx){
		System.out.println("channelInactive");
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}
}

Twisted:

# -*- coding:utf-8 –*-

from twisted.internet.protocol import Protocol
from twisted.internet.protocol import Factory
from twisted.internet import reactor

class TcpServerHandle(Protocol):
    
    # 新的连接建立
    def connectionMade(self):
        print 'connectionMade'
        
    # 连接断开
    def connectionLost(self, reason):
        print 'connectionLost'
    
    # 接收到新数据
    def dataReceived(self, data):
        print 'dataReceived', data
        self.transport.write('你好')

factory = Factory()
factory.protocol = TcpServerHandle
reactor.listenTCP(8080, factory)
reactor.run()

上面的代码可以看出,这三个框架实现的TCP服务器,在连接建立、接收到客户端传来的数据、连接关闭时,都会触发某个事件。例如接收到客户端传来的数据时,MINA会触发事件调用messageReceived,Netty会调用channelRead,Twisted会调用dataReceived。编写代码时,只需要继承一个类并重写响应的方法即可。这就是event-driven事件驱动。

下面是Java写的一个TCP客户端用作测试,客户端没有使用这三个框架,也没有使用NIO,只是一个普通的BIO的TCP客户端。

TCP在建立连接到关闭连接的过程中,可以多次进行发送和接收数据。下面的客户端发送了两个字符串到服务器并两次获取服务器回应的数据,之间通过Thread.sleep(5000)间隔5秒。

public class TcpClient {
	
	public static void main(String[] args) throws IOException, InterruptedException {
		
		
		Socket socket = null;
		OutputStream out = null;
		InputStream in = null;
		
		try{
			
			socket = new Socket("localhost", 8080);      
			out = socket.getOutputStream();
			in = socket.getInputStream();
			
		    // 请求服务器
		    out.write("第一次请求".getBytes("UTF-8"));
		    out.flush();
		            
		    // 获取服务器响应,输出
		    byte[] byteArray = new byte[1024];
		    int length = in.read(byteArray);
		    System.out.println(new String(byteArray, 0, length, "UTF-8"));
		    
		    Thread.sleep(5000);
		    
		    // 再次请求服务器
		    out.write("第二次请求".getBytes("UTF-8"));
		    out.flush();
		    
		    // 再次获取服务器响应,输出
		    byteArray = new byte[1024];
		    length = in.read(byteArray);
		    System.out.println(new String(byteArray, 0, length, "UTF-8"));
		    
		    
		} finally {
			// 关闭连接
			in.close();
			out.close();
			socket.close();
		}
		
	}

}

用客户端分别测试上面三个TCP服务器:

MINA服务器输出结果:

sessionCreated
messageReceived:第一次请求
messageReceived:第二次请求
sessionClosed

Netty服务器输出结果:

channelActive
channelRead:第一次请求
channelRead:第二次请求
channelInactive

Twisted服务器输出结果:

connectionMade
dataReceived: 第一次请求
dataReceived: 第二次请求
connectionLost


作者:叉叉哥   转载请注明出处: http://blog.csdn.net/xiao__gui/article/details/38581355




作者:xiao__gui 发表于2014-8-15 10:53:19 原文链接
阅读:6 评论:0 查看评论

相关 [mina netty twisted] 推荐:

Mina、Netty、Twisted一起学:实现简单的TCP服务器

- - CSDN博客推荐文章
MINA、Netty、Twisted为什么放在一起学习. 首先,不妨先看一下他们官方网站对其的介绍:. (Twisted官网的文案不专业啊,居然不写asynchronous). 从上面简短的介绍中,就可以发现它们的共同特点:event-driven以及asynchronous. 它们都是 事件驱动、异步的网络编程框架.

MINA网络通信框架

- - 淘宝网通用产品团队博客
Apache MINA 2是一个开发高性能和高可伸缩性网络应用程序的网络应用框架. 它提供了一个抽象的事件驱动的异步API,可以使用TCP/IP、UDP/IP、串口和虚拟机内部的管道等传输方式. Apache MINA 2可以作为开发网络应用程序的一个良好基础. Mina 的API 将真正的网络通信与我们的应用程序隔离开来,你只需要关心你要发送、.

回转铅笔笔筒:Twisted Pencil

- wonder laura - 爱…稀奇~{新鲜:科技:创意:有趣}
来自设计师Giha Woo的创意,回转铅笔笔筒(Twisted Pencil)看上去就像是用一只长长的铅笔做成的,如果斜斜地在里面放上几只铅笔,真的别有一番风味~一款小清新的设计,你喜欢吗. 亲爱的,这些东西也会对你胃口:. 香烟铅笔:Cigarette Pencil. 烤鱼铅笔袋:Grilled Fish Pencil Case.

HTTP/2 in Netty

- -
Here, we created a context for the server with a JDK SSL provider, added a couple of ciphers, and configured the Application-Layer Protocol Negotiation for HTTP/2..

底层架构-远程通讯-Mina

- - BlogJava-首页技术区
    Apache Mina是一个能够帮助用户开发高性能和高伸缩性网络应用程序的框架. 它通过Java nio技术基于TCP/IP和UDP/IP协议提供了抽象的、事件驱动的、异步的API. 1、  基于Java nio的TCP/IP和UDP/IP实现. 基于RXTX的串口通信(RS232). 2、通过filter接口实现扩展,类似于Servlet filters.

Netty系列之Netty高性能之道

- - CSDN博客推荐文章
最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用. 相比于传统基于Java序列化+BIO(同步阻塞IO)的通信框架,性能提升了8倍多. 事实上,我对这个数据并不感到惊讶,根据我5年多的NIO编程经验,通过选择合适的NIO框架,加上高性能的压缩二进制编解码技术,精心的设计Reactor线程模型,达到上述性能指标是完全有可能的.

Netty代码分析

- LightingMan - 淘宝JAVA中间件团队博客
Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序[官方定义],整体来看其包含了以下内容:1.提供了丰富的协议编解码支持,2.实现自有的buffer系统,减少复制所带来的消耗,3.整套channel的实现,4.基于事件的过程流转以及完整的网络事件响应与扩展,5.丰富的example.

socket通信框架mina使用详解(一)

- - CSDN博客编程语言推荐文章
1.mina框架基于tcp/ip,udp/ip协议栈的通信框架. 2.mina框架的执行流程:. mina框架客户端与服务器端的执行流程一致,不同的是:Ioservice的client端实现是Ioconnector,server端是IoAcceptor..  * 客户端 iohandler.  * mina框架中客户端与服务器端的执行流程一致,.

Netty 5用户指南

- - 并发编程网 - ifeve.com
原文地址: http://netty.io/wiki/user-guide-for-5.x.html     译者:光辉勇士       校对:郭蕾. 现如今我们使用通用的应用程序或者类库来实现系统之间地互相访问,比如我们经常使用一个HTTP客户端来从web服务器上获取信息,或者通过web service来执行一个远程的调用.

Netty 用户指南4.x

- - CSDN博客推荐文章
现在我们经常使用程序或者库和其他人交流信息.例如,我们经常使用http程序库去从一个web server接收信息,或者调用一个远程的web服务.然而,一个通用的传输协议或者实现有的时候不能适应我们自己的场景.例如,我们不会用http server来传输一些大的文件,Email和一些实时性的信息,例如金融方面或者有些游戏数据方面的信息.这些需要一个高度优化的协议,为了使用某一种特定的应用场景.