미나, Netty, Twisted와 함께 배우기(1): 간단한 TCP 서버 구현

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를 쓰지 않는다니)
위의 간단한 소개에서 이들의 공통된 특징인 이벤트-driven과 asynchronous를 발견할 수 있다.그것들은 모두 이벤트 구동, 비동기적인 네트워크 프로그래밍 프레임워크이다.이를 통해 알 수 있듯이 그들 사이의 공통점은 여전히 매우 뚜렷하다.그래서 저는 이 세 가지 틀을 함께 놓고 같은 기능을 실현하면 소량의 정력으로 세 가지 물건을 배울 수 있을 뿐만 아니라 그것들 간의 각 방면의 대비도 할 수 있습니다.
그 중에서 MINA와 Netty는 자바 언어를 기반으로 하고 Twisted는 Python 언어를 기반으로 한다.그러나 언어는 중점이 아니라 이념이 중점이다.
전통적인 BIO(Blocking IO/IO 차단)를 사용하여 네트워크 프로그래밍을 할 때 네트워크 IO 읽기와 쓰기를 할 때 현재 라인을 막는다. 만약에 TCP 서버를 실현한다면 모든 클라이언트 연결에 하나의 라인을 열어야 한다. 많은 라인이 어리석게 막히고 읽기와 쓰기를 기다리는 데이터로 시스템 자원의 소모가 크다.
한편, NIO(Non-Blocking IO/비차단 IO)나 AIO(Asynchronous IO/비동기 IO)는 IO 다중 복용 기술을 통해 이루어진다. 모든 연결에 하나의 라인을 만들 필요가 없다. 그 밑바닥 실현은 운영체제의 일부 특성인 select,poll,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() {
						@Override
						public void initChannel(SocketChannel ch)
								throws Exception {
							ch.pipeline().addLast(new TcpServerHandler());
						}
					});
			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는 이벤트를 터치하여 메시지 리셋을 호출하고, Netty는 채널 리셋을 호출하며, Twisted는 데이터 리셋을 호출합니다.코드를 작성할 때, 하나의 클래스를 계승하고 응답을 다시 쓰는 방법만 있으면 된다.이것이 바로 이벤트-driven 이벤트 드라이브입니다.
다음은 Java가 작성한 TCP 클라이언트입니다. 클라이언트는 이 세 가지 프레임워크를 사용하지 않았고 NIO를 사용하지 않았습니다. 일반적인 BIO의 TCP 클라이언트입니다.
TCP는 연결 해제에 대한 연결을 설정하는 과정에서 여러 번 데이터를 전송하고 수신할 수 있습니다.다음 클라이언트는 두 개의 문자열을 서버에 보내고 서버가 응답하는 데이터를 두 번 가져옵니다.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 서버 출력 결과:
sessionCreatedmessageReceived: 첫 번째 요청 messageReceived: 두 번째 요청 sessionClosed
Netty 서버 출력 결과:
channelActivechannelRead: 첫 번째 요청 channelRead: 두 번째 요청 channelInactive
Twisted 서버 출력 결과:
connectionMadedataReceived: 첫 번째 요청 dataReceived: 두 번째 요청 connectionLost
작가: 포크형 전재 출처 밝혀주세요:http://blog.csdn.net/xiao__gui/article/details/38581355

MINA, Netty, Twisted와 함께


MINA, Netty, Twisted 함께 배우기(1): 간단한 TCP 서버 구현
MINA, Netty, Twisted 함께 배우기(2): TCP 메시지 경계 문제 및 행별 메시지 분할
MINA, Netty, Twisted 함께 배우기 (3): TCP 메시지 고정 크기 접두사(Header)
MINA, Netty, Twisted 함께 배우기 (4): 맞춤형 프로토콜
MINA, Netty, Twisted 함께 배우기 (5): 통합 프로토타입
MINA, Netty, Twisted 함께 배우기 (6): session
MINA, Netty, Twisted 함께 배우기(7): 게시/구독(Publish/Subscribe)
MINA, Netty, Twisted 함께 배우기 (8): HTTP 서버
MINA, Netty, Twisted 함께 배우기 (9): 비동기 IO 및 콜백 함수
MINA, Netty, Twisted 함께 배우기 (10): 스레드 모델
MINA, Netty, Twisted 함께 배우기(11): SSL/TLS
MINA, Netty, Twisted 함께 배우기(12): HTTPS

원본 코드


https://github.com/wucao/mina-netty-twisted

좋은 웹페이지 즐겨찾기