├── .gitignore ├── README.md ├── pom.xml └── src └── main └── java └── com └── xxg └── network ├── lesson01 ├── MinaServer.java ├── NettyServer.java ├── TcpClient.java └── TwistedServer.py ├── lesson02 ├── MinaServer.java ├── NettyServer.java ├── TcpClient.java └── TwistedServer.py ├── lesson03 ├── MinaServer.java ├── NettyServer.java ├── TcpClient.java └── TwistedServer.py ├── lesson04 ├── LittleEndian.java ├── MinaServer.java ├── MyMinaDecoder.java ├── MyMinaEncoder.java ├── MyNettyDecoder.java ├── MyNettyEncoder.java ├── NettyServer.java ├── TcpClient.java └── TwistedServer.py ├── lesson05 ├── MinaProtobufDecoder.java ├── MinaProtobufEncoder.java ├── MinaServer.java ├── NettyServer.java ├── StudentMsg.java ├── StudentMsg.proto ├── StudentMsg_pb2.py ├── TcpClient.java └── TwistedServer.py ├── lesson06 ├── MinaServer.java ├── NettyServer.java ├── NettyServer2.java ├── TcpClient.java └── TwistedServer.py ├── lesson07 ├── MinaServer.java ├── NettyServer.java ├── PublishClient.java ├── SubscribeClient.java └── TwistedServer.py ├── lesson08 ├── MinaServer.java ├── NettyServer.java └── TwistedServer.py ├── lesson11 ├── MinaServer.java ├── NettyServer.java ├── SslClient.java ├── TwistedServer.py ├── cert.crt ├── private.der └── private.pem ├── lesson12 ├── 1_gw2.vsgames.cn_bundle.crt ├── 2_gw2.vsgames.cn.key ├── MinaServer.java ├── NettyServer.java ├── TwistedServer.py ├── private.der └── private.pem └── netty └── websocket └── WebSocketServer.java /.gitignore: -------------------------------------------------------------------------------- 1 | /*.iml 2 | /target 3 | /.idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《MINA、Netty、Twisted一起学》系列教程源码 2 | [MINA、Netty、Twisted一起学(一):实现简单的TCP服务器](http://xxgblog.com/2014/08/15/mina-netty-twisted-1/) 3 | 4 | [MINA、Netty、Twisted一起学(二):TCP消息边界问题及按行分割消息](http://xxgblog.com/2014/08/21/mina-netty-twisted-2/) 5 | 6 | [MINA、Netty、Twisted一起学(三):TCP消息固定大小的前缀(Header)](http://xxgblog.com/2014/08/22/mina-netty-twisted-3/) 7 | 8 | [MINA、Netty、Twisted一起学(四):定制自己的协议](http://xxgblog.com/2014/08/25/mina-netty-twisted-4/) 9 | 10 | [MINA、Netty、Twisted一起学(五):整合protobuf](http://xxgblog.com/2014/08/27/mina-netty-twisted-5/) 11 | 12 | [MINA、Netty、Twisted一起学(六):session](http://xxgblog.com/2014/09/10/mina-netty-twisted-6/) 13 | 14 | [MINA、Netty、Twisted一起学(七):发布/订阅(Publish/Subscribe)](http://xxgblog.com/2014/09/19/mina-netty-twisted-7/) 15 | 16 | [MINA、Netty、Twisted一起学(八):HTTP服务器](http://xxgblog.com/2014/09/23/mina-netty-twisted-8/) 17 | 18 | [MINA、Netty、Twisted一起学(九):异步IO和回调函数](http://xxgblog.com/2014/10/12/mina-netty-twisted-9/) 19 | 20 | [MINA、Netty、Twisted一起学(十):线程模型](http://xxgblog.com/2014/10/16/mina-netty-twisted-10/) 21 | 22 | [MINA、Netty、Twisted一起学(十一):SSL/TLS](http://xxgblog.com/2017/02/27/mina-netty-twisted-11/) 23 | 24 | [MINA、Netty、Twisted一起学(十二):HTTPS](http://xxgblog.com/2017/02/28/mina-netty-twisted-12/) 25 | 26 | [基于 Netty 实现 WebSocket 服务器](https://xxgblog.com/2021/04/14/netty-websocket/) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.xxg 8 | network 9 | 1.0.0 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 1.8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | io.netty 26 | netty-all 27 | 4.1.42.Final 28 | 29 | 30 | org.apache.mina 31 | mina-core 32 | 2.0.16 33 | 34 | 35 | org.apache.mina 36 | mina-http 37 | 2.0.16 38 | 39 | 40 | com.google.protobuf 41 | protobuf-java 42 | 2.5.0 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson01/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson01; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.service.IoAcceptor; 5 | import org.apache.mina.core.service.IoHandlerAdapter; 6 | import org.apache.mina.core.session.IoSession; 7 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 8 | 9 | import java.io.IOException; 10 | import java.net.InetSocketAddress; 11 | 12 | /** 13 | * Created by wucao on 17/2/27. 14 | */ 15 | public class MinaServer { 16 | 17 | public static void main(String[] args) throws IOException { 18 | IoAcceptor acceptor = new NioSocketAcceptor(); 19 | acceptor.setHandler(new TcpServerHandle()); 20 | acceptor.bind(new InetSocketAddress(8080)); 21 | } 22 | } 23 | 24 | class TcpServerHandle extends IoHandlerAdapter { 25 | 26 | @Override 27 | public void exceptionCaught(IoSession session, Throwable cause) throws Exception { 28 | cause.printStackTrace(); 29 | } 30 | 31 | // 接收到新的数据 32 | @Override 33 | public void messageReceived(IoSession session, Object message) throws Exception { 34 | 35 | // 接收客户端的数据 36 | IoBuffer ioBuffer = (IoBuffer) message; 37 | byte[] byteArray = new byte[ioBuffer.limit()]; 38 | ioBuffer.get(byteArray, 0, ioBuffer.limit()); 39 | System.out.println("messageReceived:" + new String(byteArray, "UTF-8")); 40 | 41 | // 发送到客户端 42 | byte[] responseByteArray = "你好".getBytes("UTF-8"); 43 | IoBuffer responseIoBuffer = IoBuffer.allocate(responseByteArray.length); 44 | responseIoBuffer.put(responseByteArray); 45 | responseIoBuffer.flip(); 46 | session.write(responseIoBuffer); 47 | } 48 | 49 | @Override 50 | public void sessionCreated(IoSession session) throws Exception { 51 | System.out.println("sessionCreated"); 52 | } 53 | 54 | @Override 55 | public void sessionClosed(IoSession session) throws Exception { 56 | System.out.println("sessionClosed"); 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson01/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson01; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.*; 6 | import io.netty.channel.nio.NioEventLoopGroup; 7 | import io.netty.channel.socket.SocketChannel; 8 | import io.netty.channel.socket.nio.NioServerSocketChannel; 9 | import io.netty.util.CharsetUtil; 10 | import io.netty.util.ReferenceCountUtil; 11 | 12 | import java.io.UnsupportedEncodingException; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class NettyServer { 18 | 19 | public static void main(String[] args) throws InterruptedException { 20 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 21 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 22 | try { 23 | ServerBootstrap b = new ServerBootstrap(); 24 | b.group(bossGroup, workerGroup) 25 | .channel(NioServerSocketChannel.class) 26 | .childHandler(new ChannelInitializer() { 27 | @Override 28 | public void initChannel(SocketChannel ch) 29 | throws Exception { 30 | ch.pipeline().addLast(new TcpServerHandler()); 31 | } 32 | }); 33 | ChannelFuture f = b.bind(8080).sync(); 34 | f.channel().closeFuture().sync(); 35 | } finally { 36 | workerGroup.shutdownGracefully(); 37 | bossGroup.shutdownGracefully(); 38 | } 39 | } 40 | } 41 | 42 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 43 | 44 | // 接收到新的数据 45 | @Override 46 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { 47 | try { 48 | // 接收客户端的数据 49 | ByteBuf in = (ByteBuf) msg; 50 | System.out.println("channelRead:" + in.toString(CharsetUtil.UTF_8)); 51 | 52 | // 发送到客户端 53 | byte[] responseByteArray = "你好".getBytes("UTF-8"); 54 | ByteBuf out = ctx.alloc().buffer(responseByteArray.length); 55 | out.writeBytes(responseByteArray); 56 | ctx.writeAndFlush(out); 57 | 58 | } finally { 59 | ReferenceCountUtil.release(msg); 60 | } 61 | } 62 | 63 | @Override 64 | public void channelActive(ChannelHandlerContext ctx) { 65 | System.out.println("channelActive"); 66 | } 67 | 68 | @Override 69 | public void channelInactive(ChannelHandlerContext ctx){ 70 | System.out.println("channelInactive"); 71 | } 72 | 73 | @Override 74 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 75 | cause.printStackTrace(); 76 | ctx.close(); 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson01/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson01; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | 8 | /** 9 | * Created by wucao on 17/2/27. 10 | */ 11 | public class TcpClient { 12 | 13 | public static void main(String[] args) throws IOException, InterruptedException { 14 | 15 | Socket socket = null; 16 | OutputStream out = null; 17 | InputStream in = null; 18 | 19 | try{ 20 | 21 | socket = new Socket("localhost", 8080); 22 | out = socket.getOutputStream(); 23 | in = socket.getInputStream(); 24 | 25 | // 请求服务器 26 | out.write("第一次请求".getBytes("UTF-8")); 27 | out.flush(); 28 | 29 | // 获取服务器响应,输出 30 | byte[] byteArray = new byte[1024]; 31 | int length = in.read(byteArray); 32 | System.out.println(new String(byteArray, 0, length, "UTF-8")); 33 | 34 | Thread.sleep(5000); 35 | 36 | // 再次请求服务器 37 | out.write("第二次请求".getBytes("UTF-8")); 38 | out.flush(); 39 | 40 | // 再次获取服务器响应,输出 41 | byteArray = new byte[1024]; 42 | length = in.read(byteArray); 43 | System.out.println(new String(byteArray, 0, length, "UTF-8")); 44 | 45 | 46 | } finally { 47 | // 关闭连接 48 | in.close(); 49 | out.close(); 50 | socket.close(); 51 | } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson01/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.internet.protocol import Protocol 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor 6 | 7 | class TcpServerHandle(Protocol): 8 | 9 | # 新的连接建立 10 | def connectionMade(self): 11 | print 'connectionMade' 12 | 13 | # 连接断开 14 | def connectionLost(self, reason): 15 | print 'connectionLost' 16 | 17 | # 接收到新数据 18 | def dataReceived(self, data): 19 | print 'dataReceived', data 20 | self.transport.write('你好') 21 | 22 | factory = Factory() 23 | factory.protocol = TcpServerHandle 24 | reactor.listenTCP(8080, factory) 25 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson02/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson02; 2 | 3 | import org.apache.mina.core.service.IoAcceptor; 4 | import org.apache.mina.core.service.IoHandlerAdapter; 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 7 | import org.apache.mina.filter.codec.textline.TextLineCodecFactory; 8 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 9 | 10 | import java.io.IOException; 11 | import java.net.InetSocketAddress; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class MinaServer { 18 | 19 | public static void main(String[] args) throws IOException { 20 | IoAcceptor acceptor = new NioSocketAcceptor(); 21 | 22 | // 添加一个Filter,用于接收、发送的内容按照"\r\n"分割 23 | acceptor.getFilterChain().addLast("codec", 24 | new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n"))); 25 | 26 | acceptor.setHandler(new TcpServerHandle()); 27 | acceptor.bind(new InetSocketAddress(8080)); 28 | } 29 | 30 | } 31 | 32 | class TcpServerHandle extends IoHandlerAdapter { 33 | 34 | @Override 35 | public void exceptionCaught(IoSession session, Throwable cause) 36 | throws Exception { 37 | cause.printStackTrace(); 38 | } 39 | 40 | // 接收到新的数据 41 | @Override 42 | public void messageReceived(IoSession session, Object message) 43 | throws Exception { 44 | 45 | // 接收客户端的数据,这里接收到的不再是IoBuffer类型,而是字符串 46 | String line = (String) message; 47 | System.out.println("messageReceived:" + line); 48 | 49 | } 50 | 51 | @Override 52 | public void sessionCreated(IoSession session) throws Exception { 53 | System.out.println("sessionCreated"); 54 | } 55 | 56 | @Override 57 | public void sessionClosed(IoSession session) throws Exception { 58 | System.out.println("sessionClosed"); 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson02/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson02; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LineBasedFrameDecoder; 9 | import io.netty.handler.codec.string.StringDecoder; 10 | import io.netty.util.CharsetUtil; 11 | 12 | /** 13 | * Created by wucao on 17/2/27. 14 | */ 15 | public class NettyServer { 16 | public static void main(String[] args) throws InterruptedException { 17 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 18 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 19 | try { 20 | ServerBootstrap b = new ServerBootstrap(); 21 | b.group(bossGroup, workerGroup) 22 | .channel(NioServerSocketChannel.class) 23 | .childHandler(new ChannelInitializer() { 24 | @Override 25 | public void initChannel(SocketChannel ch) 26 | throws Exception { 27 | ChannelPipeline pipeline = ch.pipeline(); 28 | 29 | // LineBasedFrameDecoder按行分割消息 30 | pipeline.addLast(new LineBasedFrameDecoder(80)); 31 | // 再按UTF-8编码转成字符串 32 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 33 | 34 | pipeline.addLast(new TcpServerHandler()); 35 | } 36 | }); 37 | ChannelFuture f = b.bind(8080).sync(); 38 | f.channel().closeFuture().sync(); 39 | } finally { 40 | workerGroup.shutdownGracefully(); 41 | bossGroup.shutdownGracefully(); 42 | } 43 | } 44 | } 45 | 46 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 47 | 48 | // 接收到新的数据 49 | @Override 50 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 51 | 52 | // msg经过StringDecoder后类型不再是ByteBuf而是String 53 | String line = (String) msg; 54 | System.out.println("channelRead:" + line); 55 | } 56 | 57 | @Override 58 | public void channelActive(ChannelHandlerContext ctx) { 59 | System.out.println("channelActive"); 60 | } 61 | 62 | @Override 63 | public void channelInactive(ChannelHandlerContext ctx) { 64 | System.out.println("channelInactive"); 65 | } 66 | 67 | @Override 68 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 69 | cause.printStackTrace(); 70 | ctx.close(); 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson02/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson02; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.net.Socket; 6 | 7 | /** 8 | * Created by wucao on 17/2/27. 9 | */ 10 | public class TcpClient { 11 | 12 | public static void main(String[] args) throws IOException, InterruptedException { 13 | 14 | Socket socket = null; 15 | OutputStream out = null; 16 | 17 | try{ 18 | 19 | socket = new Socket("localhost", 8080); 20 | out = socket.getOutputStream(); 21 | 22 | String lines = "床前"; 23 | byte[] outputBytes = lines.getBytes("UTF-8"); 24 | out.write(outputBytes); 25 | out.flush(); 26 | 27 | Thread.sleep(1000); 28 | 29 | lines = "明月"; 30 | outputBytes = lines.getBytes("UTF-8"); 31 | out.write(outputBytes); 32 | out.flush(); 33 | 34 | Thread.sleep(1000); 35 | 36 | lines = "光\r\n疑是地上霜\r\n举头"; 37 | outputBytes = lines.getBytes("UTF-8"); 38 | out.write(outputBytes); 39 | out.flush(); 40 | 41 | Thread.sleep(1000); 42 | 43 | lines = "望明月\r\n低头思故乡\r\n"; 44 | outputBytes = lines.getBytes("UTF-8"); 45 | out.write(outputBytes); 46 | out.flush(); 47 | 48 | } finally { 49 | // 关闭连接 50 | out.close(); 51 | socket.close(); 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson02/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.protocols.basic import LineOnlyReceiver 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor 6 | 7 | class TcpServerHandle(LineOnlyReceiver): 8 | 9 | # 新的连接建立 10 | def connectionMade(self): 11 | print 'connectionMade' 12 | 13 | # 连接断开 14 | def connectionLost(self, reason): 15 | print 'connectionLost' 16 | 17 | # 接收到新的一行数据 18 | def lineReceived(self, data): 19 | print 'lineReceived:' + data 20 | 21 | factory = Factory() 22 | factory.protocol = TcpServerHandle 23 | reactor.listenTCP(8080, factory) 24 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson03/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson03; 2 | 3 | import org.apache.mina.core.service.IoAcceptor; 4 | import org.apache.mina.core.service.IoHandlerAdapter; 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 7 | import org.apache.mina.filter.codec.prefixedstring.PrefixedStringCodecFactory; 8 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 9 | 10 | import java.io.IOException; 11 | import java.net.InetSocketAddress; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class MinaServer { 18 | 19 | public static void main(String[] args) throws IOException { 20 | IoAcceptor acceptor = new NioSocketAcceptor(); 21 | 22 | // 4字节的Header指定Body的字节数,对这种消息的处理 23 | acceptor.getFilterChain().addLast("codec", 24 | new ProtocolCodecFilter(new PrefixedStringCodecFactory(Charset.forName("UTF-8")))); 25 | 26 | acceptor.setHandler(new TcpServerHandle()); 27 | acceptor.bind(new InetSocketAddress(8080)); 28 | } 29 | } 30 | 31 | class TcpServerHandle extends IoHandlerAdapter { 32 | 33 | @Override 34 | public void exceptionCaught(IoSession session, Throwable cause) 35 | throws Exception { 36 | cause.printStackTrace(); 37 | } 38 | 39 | // 接收到新的数据 40 | @Override 41 | public void messageReceived(IoSession session, Object message) 42 | throws Exception { 43 | 44 | String msg = (String) message; 45 | System.out.println("messageReceived:" + msg); 46 | 47 | } 48 | 49 | @Override 50 | public void sessionCreated(IoSession session) throws Exception { 51 | System.out.println("sessionCreated"); 52 | } 53 | 54 | @Override 55 | public void sessionClosed(IoSession session) throws Exception { 56 | System.out.println("sessionClosed"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson03/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson03; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 9 | import io.netty.handler.codec.string.StringDecoder; 10 | import io.netty.util.CharsetUtil; 11 | 12 | /** 13 | * Created by wucao on 17/2/27. 14 | */ 15 | public class NettyServer { 16 | 17 | public static void main(String[] args) throws InterruptedException { 18 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 19 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 20 | try { 21 | ServerBootstrap b = new ServerBootstrap(); 22 | b.group(bossGroup, workerGroup) 23 | .channel(NioServerSocketChannel.class) 24 | .childHandler(new ChannelInitializer() { 25 | @Override 26 | public void initChannel(SocketChannel ch) 27 | throws Exception { 28 | ChannelPipeline pipeline = ch.pipeline(); 29 | 30 | // LengthFieldBasedFrameDecoder按行分割消息,取出body 31 | pipeline.addLast(new LengthFieldBasedFrameDecoder(80, 0, 4, 0, 4)); 32 | // 再按UTF-8编码转成字符串 33 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 34 | 35 | pipeline.addLast(new TcpServerHandler()); 36 | } 37 | }); 38 | ChannelFuture f = b.bind(8080).sync(); 39 | f.channel().closeFuture().sync(); 40 | } finally { 41 | workerGroup.shutdownGracefully(); 42 | bossGroup.shutdownGracefully(); 43 | } 44 | } 45 | } 46 | 47 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 48 | 49 | // 接收到新的数据 50 | @Override 51 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 52 | 53 | String message = (String) msg; 54 | System.out.println("channelRead:" + message); 55 | } 56 | 57 | @Override 58 | public void channelActive(ChannelHandlerContext ctx) { 59 | System.out.println("channelActive"); 60 | } 61 | 62 | @Override 63 | public void channelInactive(ChannelHandlerContext ctx) { 64 | System.out.println("channelInactive"); 65 | } 66 | 67 | @Override 68 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 69 | cause.printStackTrace(); 70 | ctx.close(); 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson03/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson03; 2 | 3 | import java.io.DataOutputStream; 4 | import java.io.IOException; 5 | import java.net.Socket; 6 | 7 | /** 8 | * Created by wucao on 17/2/27. 9 | */ 10 | public class TcpClient { 11 | 12 | public static void main(String[] args) throws IOException { 13 | 14 | Socket socket = null; 15 | DataOutputStream out = null; 16 | 17 | try { 18 | 19 | socket = new Socket("localhost", 8080); 20 | out = new DataOutputStream(socket.getOutputStream()); 21 | 22 | // 请求服务器 23 | String data1 = "牛顿"; 24 | byte[] outputBytes1 = data1.getBytes("UTF-8"); 25 | out.writeInt(outputBytes1.length); // write header 26 | out.write(outputBytes1); // write body 27 | 28 | String data2 = "爱因斯坦"; 29 | byte[] outputBytes2 = data2.getBytes("UTF-8"); 30 | out.writeInt(outputBytes2.length); // write header 31 | out.write(outputBytes2); // write body 32 | 33 | out.flush(); 34 | 35 | } finally { 36 | // 关闭连接 37 | out.close(); 38 | socket.close(); 39 | } 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson03/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.protocols.basic import Int32StringReceiver 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor 6 | 7 | class TcpServerHandle(Int32StringReceiver): 8 | 9 | # 新的连接建立 10 | def connectionMade(self): 11 | print 'connectionMade' 12 | 13 | # 连接断开 14 | def connectionLost(self, reason): 15 | print 'connectionLost' 16 | 17 | # 接收到新的数据 18 | def stringReceived(self, data): 19 | print 'stringReceived:' + data 20 | 21 | factory = Factory() 22 | factory.protocol = TcpServerHandle 23 | reactor.listenTCP(8080, factory) 24 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/LittleEndian.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | /** 4 | * Created by wucao on 17/2/27. 5 | */ 6 | public class LittleEndian { 7 | 8 | /** 9 | * 将int转成4字节的小字节序字节数组 10 | */ 11 | public static byte[] toLittleEndian(int i) { 12 | byte[] bytes = new byte[4]; 13 | bytes[0] = (byte) i; 14 | bytes[1] = (byte) (i >>> 8); 15 | bytes[2] = (byte) (i >>> 16); 16 | bytes[3] = (byte) (i >>> 24); 17 | return bytes; 18 | } 19 | 20 | /** 21 | * 将小字节序的4字节的字节数组转成int 22 | */ 23 | public static int getLittleEndianInt(byte[] bytes) { 24 | int b0 = bytes[0] & 0xFF; 25 | int b1 = bytes[1] & 0xFF; 26 | int b2 = bytes[2] & 0xFF; 27 | int b3 = bytes[3] & 0xFF; 28 | return b0 + (b1 << 8) + (b2 << 16) + (b3 << 24); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import org.apache.mina.core.service.IoAcceptor; 4 | import org.apache.mina.core.service.IoHandlerAdapter; 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 7 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 8 | 9 | import java.io.IOException; 10 | import java.net.InetSocketAddress; 11 | 12 | /** 13 | * Created by wucao on 17/2/27. 14 | */ 15 | public class MinaServer { 16 | 17 | public static void main(String[] args) throws IOException { 18 | IoAcceptor acceptor = new NioSocketAcceptor(); 19 | 20 | // 指定编码解码器 21 | acceptor.getFilterChain().addLast("codec", 22 | new ProtocolCodecFilter(new MyMinaEncoder(), new MyMinaDecoder())); 23 | 24 | acceptor.setHandler(new TcpServerHandle()); 25 | acceptor.bind(new InetSocketAddress(8080)); 26 | } 27 | } 28 | 29 | class TcpServerHandle extends IoHandlerAdapter { 30 | 31 | @Override 32 | public void exceptionCaught(IoSession session, Throwable cause) 33 | throws Exception { 34 | cause.printStackTrace(); 35 | } 36 | 37 | // 接收到新的数据 38 | @Override 39 | public void messageReceived(IoSession session, Object message) 40 | throws Exception { 41 | 42 | // MyMinaDecoder将接收到的数据由IoBuffer转为String 43 | String msg = (String) message; 44 | System.out.println("messageReceived:" + msg); 45 | 46 | // MyMinaEncoder将write的字符串添加了一个小字节序Header并转为字节码 47 | session.write("收到"); 48 | } 49 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/MyMinaDecoder.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.session.IoSession; 5 | import org.apache.mina.filter.codec.CumulativeProtocolDecoder; 6 | import org.apache.mina.filter.codec.ProtocolDecoderOutput; 7 | 8 | /** 9 | * Created by wucao on 17/2/27. 10 | */ 11 | public class MyMinaDecoder extends CumulativeProtocolDecoder { 12 | 13 | @Override 14 | protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { 15 | 16 | // 如果没有接收完Header部分(4字节),直接返回false 17 | if(in.remaining() < 4) { 18 | return false; 19 | } else { 20 | 21 | // 标记开始位置,如果一条消息没传输完成则返回到这个位置 22 | in.mark(); 23 | 24 | byte[] bytes = new byte[4]; 25 | in.get(bytes); // 读取4字节的Header 26 | 27 | int bodyLength = LittleEndian.getLittleEndianInt(bytes); // 按小字节序转int 28 | 29 | // 如果body没有接收完整,直接返回false 30 | if(in.remaining() < bodyLength) { 31 | in.reset(); // IoBuffer position回到原来标记的地方 32 | return false; 33 | } else { 34 | byte[] bodyBytes = new byte[bodyLength]; 35 | in.get(bodyBytes); 36 | String body = new String(bodyBytes, "UTF-8"); 37 | out.write(body); // 解析出一条消息 38 | return true; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/MyMinaEncoder.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.session.IoSession; 5 | import org.apache.mina.filter.codec.ProtocolEncoderAdapter; 6 | import org.apache.mina.filter.codec.ProtocolEncoderOutput; 7 | 8 | /** 9 | * Created by wucao on 17/2/27. 10 | */ 11 | public class MyMinaEncoder extends ProtocolEncoderAdapter { 12 | 13 | @Override 14 | public void encode(IoSession session, Object message, 15 | ProtocolEncoderOutput out) throws Exception { 16 | 17 | String msg = (String) message; 18 | byte[] bytes = msg.getBytes("UTF-8"); 19 | int length = bytes.length; 20 | byte[] header = LittleEndian.toLittleEndian(length); // 按小字节序转成字节数组 21 | 22 | IoBuffer buffer = IoBuffer.allocate(length + 4); 23 | buffer.put(header); // header 24 | buffer.put(bytes); // body 25 | buffer.flip(); 26 | out.write(buffer); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/MyNettyDecoder.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.ByteToMessageDecoder; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by wucao on 17/2/27. 11 | */ 12 | public class MyNettyDecoder extends ByteToMessageDecoder { 13 | 14 | @Override 15 | protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { 16 | 17 | // 如果没有接收完Header部分(4字节),直接退出该方法 18 | if(in.readableBytes() >= 4) { 19 | 20 | // 标记开始位置,如果一条消息没传输完成则返回到这个位置 21 | in.markReaderIndex(); 22 | 23 | byte[] bytes = new byte[4]; 24 | in.readBytes(bytes); // 读取4字节的Header 25 | 26 | int bodyLength = LittleEndian.getLittleEndianInt(bytes); // header按小字节序转int 27 | 28 | // 如果body没有接收完整 29 | if(in.readableBytes() < bodyLength) { 30 | in.resetReaderIndex(); // ByteBuf回到标记位置 31 | } else { 32 | byte[] bodyBytes = new byte[bodyLength]; 33 | in.readBytes(bodyBytes); 34 | String body = new String(bodyBytes, "UTF-8"); 35 | out.add(body); // 解析出一条消息 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/MyNettyEncoder.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandlerContext; 5 | import io.netty.handler.codec.MessageToByteEncoder; 6 | 7 | /** 8 | * Created by wucao on 17/2/27. 9 | */ 10 | public class MyNettyEncoder extends MessageToByteEncoder { 11 | 12 | @Override 13 | protected void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) 14 | throws Exception { 15 | 16 | byte[] bytes = msg.getBytes("UTF-8"); 17 | int length = bytes.length; 18 | byte[] header = LittleEndian.toLittleEndian(length); // int按小字节序转字节数组 19 | out.writeBytes(header); // write header 20 | out.writeBytes(bytes); // write body 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | 9 | /** 10 | * Created by wucao on 17/2/27. 11 | */ 12 | public class NettyServer { 13 | 14 | public static void main(String[] args) throws InterruptedException { 15 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 16 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 17 | try { 18 | ServerBootstrap b = new ServerBootstrap(); 19 | b.group(bossGroup, workerGroup) 20 | .channel(NioServerSocketChannel.class) 21 | .childHandler(new ChannelInitializer() { 22 | @Override 23 | public void initChannel(SocketChannel ch) 24 | throws Exception { 25 | ChannelPipeline pipeline = ch.pipeline(); 26 | 27 | // 加上自己的Encoder和Decoder 28 | pipeline.addLast(new MyNettyDecoder()); 29 | pipeline.addLast(new MyNettyEncoder()); 30 | 31 | pipeline.addLast(new TcpServerHandler()); 32 | } 33 | }); 34 | ChannelFuture f = b.bind(8080).sync(); 35 | f.channel().closeFuture().sync(); 36 | } finally { 37 | workerGroup.shutdownGracefully(); 38 | bossGroup.shutdownGracefully(); 39 | } 40 | } 41 | } 42 | 43 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 44 | 45 | // 接收到新的数据 46 | @Override 47 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 48 | 49 | // MyNettyDecoder将接收到的数据由ByteBuf转为String 50 | String message = (String) msg; 51 | System.out.println("channelRead:" + message); 52 | 53 | // MyNettyEncoder将write的字符串添加了一个小字节序Header并转为字节码 54 | ctx.writeAndFlush("收到"); 55 | } 56 | 57 | @Override 58 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 59 | cause.printStackTrace(); 60 | ctx.close(); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson04; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.OutputStream; 6 | import java.net.Socket; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Created by wucao on 17/2/27. 11 | */ 12 | public class TcpClient { 13 | 14 | public static void main(String[] args) throws IOException { 15 | 16 | Socket socket = null; 17 | OutputStream out = null; 18 | InputStream in = null; 19 | 20 | try { 21 | 22 | socket = new Socket("localhost", 8080); 23 | out = socket.getOutputStream(); 24 | in = socket.getInputStream(); 25 | 26 | // 请求服务器 27 | String data = "我是客户端"; 28 | byte[] outputBytes = data.getBytes("UTF-8"); 29 | out.write(LittleEndian.toLittleEndian(outputBytes.length)); // write header 30 | out.write(outputBytes); // write body 31 | out.flush(); 32 | 33 | // 获取响应 34 | byte[] inputBytes = new byte[1024]; 35 | int length = in.read(inputBytes); 36 | if(length >= 4) { 37 | int bodyLength = LittleEndian.getLittleEndianInt(inputBytes); 38 | if(length >= 4 + bodyLength) { 39 | byte[] bodyBytes = Arrays.copyOfRange(inputBytes, 4, 4 + bodyLength); 40 | System.out.println("Header:" + bodyLength); 41 | System.out.println("Body:" + new String(bodyBytes, "UTf-8")); 42 | } 43 | } 44 | 45 | } finally { 46 | // 关闭连接 47 | in.close(); 48 | out.close(); 49 | socket.close(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson04/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from struct import pack, unpack 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet.protocol import Protocol 6 | from twisted.internet import reactor 7 | 8 | # 编码、解码器 9 | class MyProtocol(Protocol): 10 | 11 | # 用于暂时存放接收到的数据 12 | _buffer = b"" 13 | 14 | def dataReceived(self, data): 15 | # 上次未处理的数据加上本次接收到的数据 16 | self._buffer = self._buffer + data 17 | # 一直循环直到新的消息没有接收完整 18 | while True: 19 | # 如果header接收完整 20 | if len(self._buffer) >= 4: 21 | # 按小字节序转int 22 | length, = unpack("= 4 + length: 25 | # body部分 26 | packet = self._buffer[4:4 + length] 27 | # 新的一条消息接收并解码完成,调用stringReceived 28 | self.stringReceived(packet) 29 | # 去掉_buffer中已经处理的消息部分 30 | self._buffer = self._buffer[4 + length:] 31 | else: 32 | break; 33 | else: 34 | break; 35 | 36 | def stringReceived(self, data): 37 | raise NotImplementedError 38 | 39 | def sendString(self, string): 40 | self.transport.write(pack(" friends = student.getFriendsList(); 49 | for(String friend : friends) { 50 | System.out.println(friend); 51 | } 52 | 53 | // 新建一个Student对象传到客户端 54 | StudentMsg.Student.Builder builder = StudentMsg.Student.newBuilder(); 55 | builder.setId(9); 56 | builder.setName("服务器"); 57 | builder.setEmail("123@abc.com"); 58 | builder.addFriends("X"); 59 | builder.addFriends("Y"); 60 | StudentMsg.Student student2 = builder.build(); 61 | session.write(student2); 62 | } 63 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson05; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 9 | import io.netty.handler.codec.LengthFieldPrepender; 10 | import io.netty.handler.codec.protobuf.ProtobufDecoder; 11 | import io.netty.handler.codec.protobuf.ProtobufEncoder; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * Created by wucao on 17/2/27. 17 | */ 18 | public class NettyServer { 19 | 20 | public static void main(String[] args) throws InterruptedException { 21 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 22 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 23 | try { 24 | ServerBootstrap b = new ServerBootstrap(); 25 | b.group(bossGroup, workerGroup) 26 | .channel(NioServerSocketChannel.class) 27 | .childHandler(new ChannelInitializer() { 28 | @Override 29 | public void initChannel(SocketChannel ch) 30 | throws Exception { 31 | ChannelPipeline pipeline = ch.pipeline(); 32 | 33 | // 负责通过4字节Header指定的Body长度将消息切割 34 | pipeline.addLast("frameDecoder", 35 | new LengthFieldBasedFrameDecoder(1048576, 0, 4, 0, 4)); 36 | 37 | // 负责将frameDecoder处理后的完整的一条消息的protobuf字节码转成Student对象 38 | pipeline.addLast("protobufDecoder", 39 | new ProtobufDecoder(StudentMsg.Student.getDefaultInstance())); 40 | 41 | // 负责将写入的字节码加上4字节Header前缀来指定Body长度 42 | pipeline.addLast("frameEncoder", new LengthFieldPrepender(4)); 43 | 44 | // 负责将Student对象转成protobuf字节码 45 | pipeline.addLast("protobufEncoder", new ProtobufEncoder()); 46 | 47 | pipeline.addLast(new TcpServerHandler()); 48 | } 49 | }); 50 | ChannelFuture f = b.bind(8080).sync(); 51 | f.channel().closeFuture().sync(); 52 | } finally { 53 | workerGroup.shutdownGracefully(); 54 | bossGroup.shutdownGracefully(); 55 | } 56 | } 57 | } 58 | 59 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 60 | 61 | @Override 62 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 63 | 64 | // 读取客户端传过来的Student对象 65 | StudentMsg.Student student = (StudentMsg.Student) msg; 66 | System.out.println("ID:" + student.getId()); 67 | System.out.println("Name:" + student.getName()); 68 | System.out.println("Email:" + student.getEmail()); 69 | System.out.println("Friends:"); 70 | List friends = student.getFriendsList(); 71 | for(String friend : friends) { 72 | System.out.println(friend); 73 | } 74 | 75 | // 新建一个Student对象传到客户端 76 | StudentMsg.Student.Builder builder = StudentMsg.Student.newBuilder(); 77 | builder.setId(9); 78 | builder.setName("服务器"); 79 | builder.setEmail("123@abc.com"); 80 | builder.addFriends("X"); 81 | builder.addFriends("Y"); 82 | StudentMsg.Student student2 = builder.build(); 83 | ctx.writeAndFlush(student2); 84 | } 85 | 86 | @Override 87 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 88 | cause.printStackTrace(); 89 | ctx.close(); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/StudentMsg.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson05;// Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: StudentMsg.proto 3 | 4 | public final class StudentMsg { 5 | private StudentMsg() {} 6 | public static void registerAllExtensions( 7 | com.google.protobuf.ExtensionRegistry registry) { 8 | } 9 | public interface StudentOrBuilder 10 | extends com.google.protobuf.MessageOrBuilder { 11 | 12 | // required int32 id = 1; 13 | /** 14 | * required int32 id = 1; 15 | * 16 | *
  17 |      * ID
  18 |      * 
19 | */ 20 | boolean hasId(); 21 | /** 22 | * required int32 id = 1; 23 | * 24 | *
  25 |      * ID
  26 |      * 
27 | */ 28 | int getId(); 29 | 30 | // required string name = 2; 31 | /** 32 | * required string name = 2; 33 | * 34 | *
  35 |      * ����
  36 |      * 
37 | */ 38 | boolean hasName(); 39 | /** 40 | * required string name = 2; 41 | * 42 | *
  43 |      * ����
  44 |      * 
45 | */ 46 | String getName(); 47 | /** 48 | * required string name = 2; 49 | * 50 | *
  51 |      * ����
  52 |      * 
53 | */ 54 | com.google.protobuf.ByteString 55 | getNameBytes(); 56 | 57 | // optional string email = 3; 58 | /** 59 | * optional string email = 3; 60 | * 61 | *
  62 |      * email
  63 |      * 
64 | */ 65 | boolean hasEmail(); 66 | /** 67 | * optional string email = 3; 68 | * 69 | *
  70 |      * email
  71 |      * 
72 | */ 73 | String getEmail(); 74 | /** 75 | * optional string email = 3; 76 | * 77 | *
  78 |      * email
  79 |      * 
80 | */ 81 | com.google.protobuf.ByteString 82 | getEmailBytes(); 83 | 84 | // repeated string friends = 4; 85 | /** 86 | * repeated string friends = 4; 87 | * 88 | *
  89 |      * ����
  90 |      * 
91 | */ 92 | java.util.List 93 | getFriendsList(); 94 | /** 95 | * repeated string friends = 4; 96 | * 97 | *
  98 |      * ����
  99 |      * 
100 | */ 101 | int getFriendsCount(); 102 | /** 103 | * repeated string friends = 4; 104 | * 105 | *
 106 |      * ����
 107 |      * 
108 | */ 109 | String getFriends(int index); 110 | /** 111 | * repeated string friends = 4; 112 | * 113 | *
 114 |      * ����
 115 |      * 
116 | */ 117 | com.google.protobuf.ByteString 118 | getFriendsBytes(int index); 119 | } 120 | /** 121 | * Protobuf type {@code Student} 122 | */ 123 | public static final class Student extends 124 | com.google.protobuf.GeneratedMessage 125 | implements StudentOrBuilder { 126 | // Use Student.newBuilder() to construct. 127 | private Student(com.google.protobuf.GeneratedMessage.Builder builder) { 128 | super(builder); 129 | this.unknownFields = builder.getUnknownFields(); 130 | } 131 | private Student(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); } 132 | 133 | private static final Student defaultInstance; 134 | public static Student getDefaultInstance() { 135 | return defaultInstance; 136 | } 137 | 138 | public Student getDefaultInstanceForType() { 139 | return defaultInstance; 140 | } 141 | 142 | private final com.google.protobuf.UnknownFieldSet unknownFields; 143 | @Override 144 | public final com.google.protobuf.UnknownFieldSet 145 | getUnknownFields() { 146 | return this.unknownFields; 147 | } 148 | private Student( 149 | com.google.protobuf.CodedInputStream input, 150 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 151 | throws com.google.protobuf.InvalidProtocolBufferException { 152 | initFields(); 153 | int mutable_bitField0_ = 0; 154 | com.google.protobuf.UnknownFieldSet.Builder unknownFields = 155 | com.google.protobuf.UnknownFieldSet.newBuilder(); 156 | try { 157 | boolean done = false; 158 | while (!done) { 159 | int tag = input.readTag(); 160 | switch (tag) { 161 | case 0: 162 | done = true; 163 | break; 164 | default: { 165 | if (!parseUnknownField(input, unknownFields, 166 | extensionRegistry, tag)) { 167 | done = true; 168 | } 169 | break; 170 | } 171 | case 8: { 172 | bitField0_ |= 0x00000001; 173 | id_ = input.readInt32(); 174 | break; 175 | } 176 | case 18: { 177 | bitField0_ |= 0x00000002; 178 | name_ = input.readBytes(); 179 | break; 180 | } 181 | case 26: { 182 | bitField0_ |= 0x00000004; 183 | email_ = input.readBytes(); 184 | break; 185 | } 186 | case 34: { 187 | if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { 188 | friends_ = new com.google.protobuf.LazyStringArrayList(); 189 | mutable_bitField0_ |= 0x00000008; 190 | } 191 | friends_.add(input.readBytes()); 192 | break; 193 | } 194 | } 195 | } 196 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 197 | throw e.setUnfinishedMessage(this); 198 | } catch (java.io.IOException e) { 199 | throw new com.google.protobuf.InvalidProtocolBufferException( 200 | e.getMessage()).setUnfinishedMessage(this); 201 | } finally { 202 | if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { 203 | friends_ = new com.google.protobuf.UnmodifiableLazyStringList(friends_); 204 | } 205 | this.unknownFields = unknownFields.build(); 206 | makeExtensionsImmutable(); 207 | } 208 | } 209 | public static final com.google.protobuf.Descriptors.Descriptor 210 | getDescriptor() { 211 | return StudentMsg.internal_static_Student_descriptor; 212 | } 213 | 214 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 215 | internalGetFieldAccessorTable() { 216 | return StudentMsg.internal_static_Student_fieldAccessorTable 217 | .ensureFieldAccessorsInitialized( 218 | Student.class, Builder.class); 219 | } 220 | 221 | public static com.google.protobuf.Parser PARSER = 222 | new com.google.protobuf.AbstractParser() { 223 | public Student parsePartialFrom( 224 | com.google.protobuf.CodedInputStream input, 225 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 226 | throws com.google.protobuf.InvalidProtocolBufferException { 227 | return new Student(input, extensionRegistry); 228 | } 229 | }; 230 | 231 | @Override 232 | public com.google.protobuf.Parser getParserForType() { 233 | return PARSER; 234 | } 235 | 236 | private int bitField0_; 237 | // required int32 id = 1; 238 | public static final int ID_FIELD_NUMBER = 1; 239 | private int id_; 240 | /** 241 | * required int32 id = 1; 242 | * 243 | *
 244 |      * ID
 245 |      * 
246 | */ 247 | public boolean hasId() { 248 | return ((bitField0_ & 0x00000001) == 0x00000001); 249 | } 250 | /** 251 | * required int32 id = 1; 252 | * 253 | *
 254 |      * ID
 255 |      * 
256 | */ 257 | public int getId() { 258 | return id_; 259 | } 260 | 261 | // required string name = 2; 262 | public static final int NAME_FIELD_NUMBER = 2; 263 | private Object name_; 264 | /** 265 | * required string name = 2; 266 | * 267 | *
 268 |      * ����
 269 |      * 
270 | */ 271 | public boolean hasName() { 272 | return ((bitField0_ & 0x00000002) == 0x00000002); 273 | } 274 | /** 275 | * required string name = 2; 276 | * 277 | *
 278 |      * ����
 279 |      * 
280 | */ 281 | public String getName() { 282 | Object ref = name_; 283 | if (ref instanceof String) { 284 | return (String) ref; 285 | } else { 286 | com.google.protobuf.ByteString bs = 287 | (com.google.protobuf.ByteString) ref; 288 | String s = bs.toStringUtf8(); 289 | if (bs.isValidUtf8()) { 290 | name_ = s; 291 | } 292 | return s; 293 | } 294 | } 295 | /** 296 | * required string name = 2; 297 | * 298 | *
 299 |      * ����
 300 |      * 
301 | */ 302 | public com.google.protobuf.ByteString 303 | getNameBytes() { 304 | Object ref = name_; 305 | if (ref instanceof String) { 306 | com.google.protobuf.ByteString b = 307 | com.google.protobuf.ByteString.copyFromUtf8( 308 | (String) ref); 309 | name_ = b; 310 | return b; 311 | } else { 312 | return (com.google.protobuf.ByteString) ref; 313 | } 314 | } 315 | 316 | // optional string email = 3; 317 | public static final int EMAIL_FIELD_NUMBER = 3; 318 | private Object email_; 319 | /** 320 | * optional string email = 3; 321 | * 322 | *
 323 |      * email
 324 |      * 
325 | */ 326 | public boolean hasEmail() { 327 | return ((bitField0_ & 0x00000004) == 0x00000004); 328 | } 329 | /** 330 | * optional string email = 3; 331 | * 332 | *
 333 |      * email
 334 |      * 
335 | */ 336 | public String getEmail() { 337 | Object ref = email_; 338 | if (ref instanceof String) { 339 | return (String) ref; 340 | } else { 341 | com.google.protobuf.ByteString bs = 342 | (com.google.protobuf.ByteString) ref; 343 | String s = bs.toStringUtf8(); 344 | if (bs.isValidUtf8()) { 345 | email_ = s; 346 | } 347 | return s; 348 | } 349 | } 350 | /** 351 | * optional string email = 3; 352 | * 353 | *
 354 |      * email
 355 |      * 
356 | */ 357 | public com.google.protobuf.ByteString 358 | getEmailBytes() { 359 | Object ref = email_; 360 | if (ref instanceof String) { 361 | com.google.protobuf.ByteString b = 362 | com.google.protobuf.ByteString.copyFromUtf8( 363 | (String) ref); 364 | email_ = b; 365 | return b; 366 | } else { 367 | return (com.google.protobuf.ByteString) ref; 368 | } 369 | } 370 | 371 | // repeated string friends = 4; 372 | public static final int FRIENDS_FIELD_NUMBER = 4; 373 | private com.google.protobuf.LazyStringList friends_; 374 | /** 375 | * repeated string friends = 4; 376 | * 377 | *
 378 |      * ����
 379 |      * 
380 | */ 381 | public java.util.List 382 | getFriendsList() { 383 | return friends_; 384 | } 385 | /** 386 | * repeated string friends = 4; 387 | * 388 | *
 389 |      * ����
 390 |      * 
391 | */ 392 | public int getFriendsCount() { 393 | return friends_.size(); 394 | } 395 | /** 396 | * repeated string friends = 4; 397 | * 398 | *
 399 |      * ����
 400 |      * 
401 | */ 402 | public String getFriends(int index) { 403 | return friends_.get(index); 404 | } 405 | /** 406 | * repeated string friends = 4; 407 | * 408 | *
 409 |      * ����
 410 |      * 
411 | */ 412 | public com.google.protobuf.ByteString 413 | getFriendsBytes(int index) { 414 | return friends_.getByteString(index); 415 | } 416 | 417 | private void initFields() { 418 | id_ = 0; 419 | name_ = ""; 420 | email_ = ""; 421 | friends_ = com.google.protobuf.LazyStringArrayList.EMPTY; 422 | } 423 | private byte memoizedIsInitialized = -1; 424 | public final boolean isInitialized() { 425 | byte isInitialized = memoizedIsInitialized; 426 | if (isInitialized != -1) return isInitialized == 1; 427 | 428 | if (!hasId()) { 429 | memoizedIsInitialized = 0; 430 | return false; 431 | } 432 | if (!hasName()) { 433 | memoizedIsInitialized = 0; 434 | return false; 435 | } 436 | memoizedIsInitialized = 1; 437 | return true; 438 | } 439 | 440 | public void writeTo(com.google.protobuf.CodedOutputStream output) 441 | throws java.io.IOException { 442 | getSerializedSize(); 443 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 444 | output.writeInt32(1, id_); 445 | } 446 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 447 | output.writeBytes(2, getNameBytes()); 448 | } 449 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 450 | output.writeBytes(3, getEmailBytes()); 451 | } 452 | for (int i = 0; i < friends_.size(); i++) { 453 | output.writeBytes(4, friends_.getByteString(i)); 454 | } 455 | getUnknownFields().writeTo(output); 456 | } 457 | 458 | private int memoizedSerializedSize = -1; 459 | public int getSerializedSize() { 460 | int size = memoizedSerializedSize; 461 | if (size != -1) return size; 462 | 463 | size = 0; 464 | if (((bitField0_ & 0x00000001) == 0x00000001)) { 465 | size += com.google.protobuf.CodedOutputStream 466 | .computeInt32Size(1, id_); 467 | } 468 | if (((bitField0_ & 0x00000002) == 0x00000002)) { 469 | size += com.google.protobuf.CodedOutputStream 470 | .computeBytesSize(2, getNameBytes()); 471 | } 472 | if (((bitField0_ & 0x00000004) == 0x00000004)) { 473 | size += com.google.protobuf.CodedOutputStream 474 | .computeBytesSize(3, getEmailBytes()); 475 | } 476 | { 477 | int dataSize = 0; 478 | for (int i = 0; i < friends_.size(); i++) { 479 | dataSize += com.google.protobuf.CodedOutputStream 480 | .computeBytesSizeNoTag(friends_.getByteString(i)); 481 | } 482 | size += dataSize; 483 | size += 1 * getFriendsList().size(); 484 | } 485 | size += getUnknownFields().getSerializedSize(); 486 | memoizedSerializedSize = size; 487 | return size; 488 | } 489 | 490 | private static final long serialVersionUID = 0L; 491 | @Override 492 | protected Object writeReplace() 493 | throws java.io.ObjectStreamException { 494 | return super.writeReplace(); 495 | } 496 | 497 | public static Student parseFrom( 498 | com.google.protobuf.ByteString data) 499 | throws com.google.protobuf.InvalidProtocolBufferException { 500 | return PARSER.parseFrom(data); 501 | } 502 | public static Student parseFrom( 503 | com.google.protobuf.ByteString data, 504 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 505 | throws com.google.protobuf.InvalidProtocolBufferException { 506 | return PARSER.parseFrom(data, extensionRegistry); 507 | } 508 | public static Student parseFrom(byte[] data) 509 | throws com.google.protobuf.InvalidProtocolBufferException { 510 | return PARSER.parseFrom(data); 511 | } 512 | public static Student parseFrom( 513 | byte[] data, 514 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 515 | throws com.google.protobuf.InvalidProtocolBufferException { 516 | return PARSER.parseFrom(data, extensionRegistry); 517 | } 518 | public static Student parseFrom(java.io.InputStream input) 519 | throws java.io.IOException { 520 | return PARSER.parseFrom(input); 521 | } 522 | public static Student parseFrom( 523 | java.io.InputStream input, 524 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 525 | throws java.io.IOException { 526 | return PARSER.parseFrom(input, extensionRegistry); 527 | } 528 | public static Student parseDelimitedFrom(java.io.InputStream input) 529 | throws java.io.IOException { 530 | return PARSER.parseDelimitedFrom(input); 531 | } 532 | public static Student parseDelimitedFrom( 533 | java.io.InputStream input, 534 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 535 | throws java.io.IOException { 536 | return PARSER.parseDelimitedFrom(input, extensionRegistry); 537 | } 538 | public static Student parseFrom( 539 | com.google.protobuf.CodedInputStream input) 540 | throws java.io.IOException { 541 | return PARSER.parseFrom(input); 542 | } 543 | public static Student parseFrom( 544 | com.google.protobuf.CodedInputStream input, 545 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 546 | throws java.io.IOException { 547 | return PARSER.parseFrom(input, extensionRegistry); 548 | } 549 | 550 | public static Builder newBuilder() { return Builder.create(); } 551 | public Builder newBuilderForType() { return newBuilder(); } 552 | public static Builder newBuilder(Student prototype) { 553 | return newBuilder().mergeFrom(prototype); 554 | } 555 | public Builder toBuilder() { return newBuilder(this); } 556 | 557 | @Override 558 | protected Builder newBuilderForType( 559 | com.google.protobuf.GeneratedMessage.BuilderParent parent) { 560 | Builder builder = new Builder(parent); 561 | return builder; 562 | } 563 | /** 564 | * Protobuf type {@code Student} 565 | */ 566 | public static final class Builder extends 567 | com.google.protobuf.GeneratedMessage.Builder 568 | implements StudentOrBuilder { 569 | public static final com.google.protobuf.Descriptors.Descriptor 570 | getDescriptor() { 571 | return StudentMsg.internal_static_Student_descriptor; 572 | } 573 | 574 | protected com.google.protobuf.GeneratedMessage.FieldAccessorTable 575 | internalGetFieldAccessorTable() { 576 | return StudentMsg.internal_static_Student_fieldAccessorTable 577 | .ensureFieldAccessorsInitialized( 578 | Student.class, Builder.class); 579 | } 580 | 581 | // Construct using StudentMsg.Student.newBuilder() 582 | private Builder() { 583 | maybeForceBuilderInitialization(); 584 | } 585 | 586 | private Builder( 587 | com.google.protobuf.GeneratedMessage.BuilderParent parent) { 588 | super(parent); 589 | maybeForceBuilderInitialization(); 590 | } 591 | private void maybeForceBuilderInitialization() { 592 | if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { 593 | } 594 | } 595 | private static Builder create() { 596 | return new Builder(); 597 | } 598 | 599 | public Builder clear() { 600 | super.clear(); 601 | id_ = 0; 602 | bitField0_ = (bitField0_ & ~0x00000001); 603 | name_ = ""; 604 | bitField0_ = (bitField0_ & ~0x00000002); 605 | email_ = ""; 606 | bitField0_ = (bitField0_ & ~0x00000004); 607 | friends_ = com.google.protobuf.LazyStringArrayList.EMPTY; 608 | bitField0_ = (bitField0_ & ~0x00000008); 609 | return this; 610 | } 611 | 612 | public Builder clone() { 613 | return create().mergeFrom(buildPartial()); 614 | } 615 | 616 | public com.google.protobuf.Descriptors.Descriptor 617 | getDescriptorForType() { 618 | return StudentMsg.internal_static_Student_descriptor; 619 | } 620 | 621 | public Student getDefaultInstanceForType() { 622 | return Student.getDefaultInstance(); 623 | } 624 | 625 | public Student build() { 626 | Student result = buildPartial(); 627 | if (!result.isInitialized()) { 628 | throw newUninitializedMessageException(result); 629 | } 630 | return result; 631 | } 632 | 633 | public Student buildPartial() { 634 | Student result = new Student(this); 635 | int from_bitField0_ = bitField0_; 636 | int to_bitField0_ = 0; 637 | if (((from_bitField0_ & 0x00000001) == 0x00000001)) { 638 | to_bitField0_ |= 0x00000001; 639 | } 640 | result.id_ = id_; 641 | if (((from_bitField0_ & 0x00000002) == 0x00000002)) { 642 | to_bitField0_ |= 0x00000002; 643 | } 644 | result.name_ = name_; 645 | if (((from_bitField0_ & 0x00000004) == 0x00000004)) { 646 | to_bitField0_ |= 0x00000004; 647 | } 648 | result.email_ = email_; 649 | if (((bitField0_ & 0x00000008) == 0x00000008)) { 650 | friends_ = new com.google.protobuf.UnmodifiableLazyStringList( 651 | friends_); 652 | bitField0_ = (bitField0_ & ~0x00000008); 653 | } 654 | result.friends_ = friends_; 655 | result.bitField0_ = to_bitField0_; 656 | onBuilt(); 657 | return result; 658 | } 659 | 660 | public Builder mergeFrom(com.google.protobuf.Message other) { 661 | if (other instanceof Student) { 662 | return mergeFrom((Student)other); 663 | } else { 664 | super.mergeFrom(other); 665 | return this; 666 | } 667 | } 668 | 669 | public Builder mergeFrom(Student other) { 670 | if (other == Student.getDefaultInstance()) return this; 671 | if (other.hasId()) { 672 | setId(other.getId()); 673 | } 674 | if (other.hasName()) { 675 | bitField0_ |= 0x00000002; 676 | name_ = other.name_; 677 | onChanged(); 678 | } 679 | if (other.hasEmail()) { 680 | bitField0_ |= 0x00000004; 681 | email_ = other.email_; 682 | onChanged(); 683 | } 684 | if (!other.friends_.isEmpty()) { 685 | if (friends_.isEmpty()) { 686 | friends_ = other.friends_; 687 | bitField0_ = (bitField0_ & ~0x00000008); 688 | } else { 689 | ensureFriendsIsMutable(); 690 | friends_.addAll(other.friends_); 691 | } 692 | onChanged(); 693 | } 694 | this.mergeUnknownFields(other.getUnknownFields()); 695 | return this; 696 | } 697 | 698 | public final boolean isInitialized() { 699 | if (!hasId()) { 700 | 701 | return false; 702 | } 703 | if (!hasName()) { 704 | 705 | return false; 706 | } 707 | return true; 708 | } 709 | 710 | public Builder mergeFrom( 711 | com.google.protobuf.CodedInputStream input, 712 | com.google.protobuf.ExtensionRegistryLite extensionRegistry) 713 | throws java.io.IOException { 714 | Student parsedMessage = null; 715 | try { 716 | parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); 717 | } catch (com.google.protobuf.InvalidProtocolBufferException e) { 718 | parsedMessage = (Student) e.getUnfinishedMessage(); 719 | throw e; 720 | } finally { 721 | if (parsedMessage != null) { 722 | mergeFrom(parsedMessage); 723 | } 724 | } 725 | return this; 726 | } 727 | private int bitField0_; 728 | 729 | // required int32 id = 1; 730 | private int id_ ; 731 | /** 732 | * required int32 id = 1; 733 | * 734 | *
 735 |        * ID
 736 |        * 
737 | */ 738 | public boolean hasId() { 739 | return ((bitField0_ & 0x00000001) == 0x00000001); 740 | } 741 | /** 742 | * required int32 id = 1; 743 | * 744 | *
 745 |        * ID
 746 |        * 
747 | */ 748 | public int getId() { 749 | return id_; 750 | } 751 | /** 752 | * required int32 id = 1; 753 | * 754 | *
 755 |        * ID
 756 |        * 
757 | */ 758 | public Builder setId(int value) { 759 | bitField0_ |= 0x00000001; 760 | id_ = value; 761 | onChanged(); 762 | return this; 763 | } 764 | /** 765 | * required int32 id = 1; 766 | * 767 | *
 768 |        * ID
 769 |        * 
770 | */ 771 | public Builder clearId() { 772 | bitField0_ = (bitField0_ & ~0x00000001); 773 | id_ = 0; 774 | onChanged(); 775 | return this; 776 | } 777 | 778 | // required string name = 2; 779 | private Object name_ = ""; 780 | /** 781 | * required string name = 2; 782 | * 783 | *
 784 |        * ����
 785 |        * 
786 | */ 787 | public boolean hasName() { 788 | return ((bitField0_ & 0x00000002) == 0x00000002); 789 | } 790 | /** 791 | * required string name = 2; 792 | * 793 | *
 794 |        * ����
 795 |        * 
796 | */ 797 | public String getName() { 798 | Object ref = name_; 799 | if (!(ref instanceof String)) { 800 | String s = ((com.google.protobuf.ByteString) ref) 801 | .toStringUtf8(); 802 | name_ = s; 803 | return s; 804 | } else { 805 | return (String) ref; 806 | } 807 | } 808 | /** 809 | * required string name = 2; 810 | * 811 | *
 812 |        * ����
 813 |        * 
814 | */ 815 | public com.google.protobuf.ByteString 816 | getNameBytes() { 817 | Object ref = name_; 818 | if (ref instanceof String) { 819 | com.google.protobuf.ByteString b = 820 | com.google.protobuf.ByteString.copyFromUtf8( 821 | (String) ref); 822 | name_ = b; 823 | return b; 824 | } else { 825 | return (com.google.protobuf.ByteString) ref; 826 | } 827 | } 828 | /** 829 | * required string name = 2; 830 | * 831 | *
 832 |        * ����
 833 |        * 
834 | */ 835 | public Builder setName( 836 | String value) { 837 | if (value == null) { 838 | throw new NullPointerException(); 839 | } 840 | bitField0_ |= 0x00000002; 841 | name_ = value; 842 | onChanged(); 843 | return this; 844 | } 845 | /** 846 | * required string name = 2; 847 | * 848 | *
 849 |        * ����
 850 |        * 
851 | */ 852 | public Builder clearName() { 853 | bitField0_ = (bitField0_ & ~0x00000002); 854 | name_ = getDefaultInstance().getName(); 855 | onChanged(); 856 | return this; 857 | } 858 | /** 859 | * required string name = 2; 860 | * 861 | *
 862 |        * ����
 863 |        * 
864 | */ 865 | public Builder setNameBytes( 866 | com.google.protobuf.ByteString value) { 867 | if (value == null) { 868 | throw new NullPointerException(); 869 | } 870 | bitField0_ |= 0x00000002; 871 | name_ = value; 872 | onChanged(); 873 | return this; 874 | } 875 | 876 | // optional string email = 3; 877 | private Object email_ = ""; 878 | /** 879 | * optional string email = 3; 880 | * 881 | *
 882 |        * email
 883 |        * 
884 | */ 885 | public boolean hasEmail() { 886 | return ((bitField0_ & 0x00000004) == 0x00000004); 887 | } 888 | /** 889 | * optional string email = 3; 890 | * 891 | *
 892 |        * email
 893 |        * 
894 | */ 895 | public String getEmail() { 896 | Object ref = email_; 897 | if (!(ref instanceof String)) { 898 | String s = ((com.google.protobuf.ByteString) ref) 899 | .toStringUtf8(); 900 | email_ = s; 901 | return s; 902 | } else { 903 | return (String) ref; 904 | } 905 | } 906 | /** 907 | * optional string email = 3; 908 | * 909 | *
 910 |        * email
 911 |        * 
912 | */ 913 | public com.google.protobuf.ByteString 914 | getEmailBytes() { 915 | Object ref = email_; 916 | if (ref instanceof String) { 917 | com.google.protobuf.ByteString b = 918 | com.google.protobuf.ByteString.copyFromUtf8( 919 | (String) ref); 920 | email_ = b; 921 | return b; 922 | } else { 923 | return (com.google.protobuf.ByteString) ref; 924 | } 925 | } 926 | /** 927 | * optional string email = 3; 928 | * 929 | *
 930 |        * email
 931 |        * 
932 | */ 933 | public Builder setEmail( 934 | String value) { 935 | if (value == null) { 936 | throw new NullPointerException(); 937 | } 938 | bitField0_ |= 0x00000004; 939 | email_ = value; 940 | onChanged(); 941 | return this; 942 | } 943 | /** 944 | * optional string email = 3; 945 | * 946 | *
 947 |        * email
 948 |        * 
949 | */ 950 | public Builder clearEmail() { 951 | bitField0_ = (bitField0_ & ~0x00000004); 952 | email_ = getDefaultInstance().getEmail(); 953 | onChanged(); 954 | return this; 955 | } 956 | /** 957 | * optional string email = 3; 958 | * 959 | *
 960 |        * email
 961 |        * 
962 | */ 963 | public Builder setEmailBytes( 964 | com.google.protobuf.ByteString value) { 965 | if (value == null) { 966 | throw new NullPointerException(); 967 | } 968 | bitField0_ |= 0x00000004; 969 | email_ = value; 970 | onChanged(); 971 | return this; 972 | } 973 | 974 | // repeated string friends = 4; 975 | private com.google.protobuf.LazyStringList friends_ = com.google.protobuf.LazyStringArrayList.EMPTY; 976 | private void ensureFriendsIsMutable() { 977 | if (!((bitField0_ & 0x00000008) == 0x00000008)) { 978 | friends_ = new com.google.protobuf.LazyStringArrayList(friends_); 979 | bitField0_ |= 0x00000008; 980 | } 981 | } 982 | /** 983 | * repeated string friends = 4; 984 | * 985 | *
 986 |        * ����
 987 |        * 
988 | */ 989 | public java.util.List 990 | getFriendsList() { 991 | return java.util.Collections.unmodifiableList(friends_); 992 | } 993 | /** 994 | * repeated string friends = 4; 995 | * 996 | *
 997 |        * ����
 998 |        * 
999 | */ 1000 | public int getFriendsCount() { 1001 | return friends_.size(); 1002 | } 1003 | /** 1004 | * repeated string friends = 4; 1005 | * 1006 | *
1007 |        * ����
1008 |        * 
1009 | */ 1010 | public String getFriends(int index) { 1011 | return friends_.get(index); 1012 | } 1013 | /** 1014 | * repeated string friends = 4; 1015 | * 1016 | *
1017 |        * ����
1018 |        * 
1019 | */ 1020 | public com.google.protobuf.ByteString 1021 | getFriendsBytes(int index) { 1022 | return friends_.getByteString(index); 1023 | } 1024 | /** 1025 | * repeated string friends = 4; 1026 | * 1027 | *
1028 |        * ����
1029 |        * 
1030 | */ 1031 | public Builder setFriends( 1032 | int index, String value) { 1033 | if (value == null) { 1034 | throw new NullPointerException(); 1035 | } 1036 | ensureFriendsIsMutable(); 1037 | friends_.set(index, value); 1038 | onChanged(); 1039 | return this; 1040 | } 1041 | /** 1042 | * repeated string friends = 4; 1043 | * 1044 | *
1045 |        * ����
1046 |        * 
1047 | */ 1048 | public Builder addFriends( 1049 | String value) { 1050 | if (value == null) { 1051 | throw new NullPointerException(); 1052 | } 1053 | ensureFriendsIsMutable(); 1054 | friends_.add(value); 1055 | onChanged(); 1056 | return this; 1057 | } 1058 | /** 1059 | * repeated string friends = 4; 1060 | * 1061 | *
1062 |        * ����
1063 |        * 
1064 | */ 1065 | public Builder addAllFriends( 1066 | Iterable values) { 1067 | ensureFriendsIsMutable(); 1068 | super.addAll(values, friends_); 1069 | onChanged(); 1070 | return this; 1071 | } 1072 | /** 1073 | * repeated string friends = 4; 1074 | * 1075 | *
1076 |        * ����
1077 |        * 
1078 | */ 1079 | public Builder clearFriends() { 1080 | friends_ = com.google.protobuf.LazyStringArrayList.EMPTY; 1081 | bitField0_ = (bitField0_ & ~0x00000008); 1082 | onChanged(); 1083 | return this; 1084 | } 1085 | /** 1086 | * repeated string friends = 4; 1087 | * 1088 | *
1089 |        * ����
1090 |        * 
1091 | */ 1092 | public Builder addFriendsBytes( 1093 | com.google.protobuf.ByteString value) { 1094 | if (value == null) { 1095 | throw new NullPointerException(); 1096 | } 1097 | ensureFriendsIsMutable(); 1098 | friends_.add(value); 1099 | onChanged(); 1100 | return this; 1101 | } 1102 | 1103 | // @@protoc_insertion_point(builder_scope:Student) 1104 | } 1105 | 1106 | static { 1107 | defaultInstance = new Student(true); 1108 | defaultInstance.initFields(); 1109 | } 1110 | 1111 | // @@protoc_insertion_point(class_scope:Student) 1112 | } 1113 | 1114 | private static com.google.protobuf.Descriptors.Descriptor 1115 | internal_static_Student_descriptor; 1116 | private static 1117 | com.google.protobuf.GeneratedMessage.FieldAccessorTable 1118 | internal_static_Student_fieldAccessorTable; 1119 | 1120 | public static com.google.protobuf.Descriptors.FileDescriptor 1121 | getDescriptor() { 1122 | return descriptor; 1123 | } 1124 | private static com.google.protobuf.Descriptors.FileDescriptor 1125 | descriptor; 1126 | static { 1127 | String[] descriptorData = { 1128 | "\n\020StudentMsg.proto\"C\n\007Student\022\n\n\002id\030\001 \002(" + 1129 | "\005\022\014\n\004name\030\002 \002(\t\022\r\n\005email\030\003 \001(\t\022\017\n\007friend" + 1130 | "s\030\004 \003(\t" 1131 | }; 1132 | com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = 1133 | new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { 1134 | public com.google.protobuf.ExtensionRegistry assignDescriptors( 1135 | com.google.protobuf.Descriptors.FileDescriptor root) { 1136 | descriptor = root; 1137 | internal_static_Student_descriptor = 1138 | getDescriptor().getMessageTypes().get(0); 1139 | internal_static_Student_fieldAccessorTable = new 1140 | com.google.protobuf.GeneratedMessage.FieldAccessorTable( 1141 | internal_static_Student_descriptor, 1142 | new String[] { "Id", "Name", "Email", "Friends", }); 1143 | return null; 1144 | } 1145 | }; 1146 | com.google.protobuf.Descriptors.FileDescriptor 1147 | .internalBuildGeneratedFileFrom(descriptorData, 1148 | new com.google.protobuf.Descriptors.FileDescriptor[] { 1149 | }, assigner); 1150 | } 1151 | 1152 | // @@protoc_insertion_point(outer_class_scope) 1153 | } 1154 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/StudentMsg.proto: -------------------------------------------------------------------------------- 1 | message Student { 2 | // ID 3 | required int32 id = 1; 4 | 5 | // 姓名 6 | required string name = 2; 7 | 8 | // email 9 | optional string email = 3; 10 | 11 | // 朋友 12 | repeated string friends = 4; 13 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/StudentMsg_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | # source: StudentMsg.proto 3 | 4 | from google.protobuf import descriptor as _descriptor 5 | from google.protobuf import message as _message 6 | from google.protobuf import reflection as _reflection 7 | from google.protobuf import descriptor_pb2 8 | # @@protoc_insertion_point(imports) 9 | 10 | 11 | 12 | 13 | DESCRIPTOR = _descriptor.FileDescriptor( 14 | name='StudentMsg.proto', 15 | package='', 16 | serialized_pb='\n\x10StudentMsg.proto\"C\n\x07Student\x12\n\n\x02id\x18\x01 \x02(\x05\x12\x0c\n\x04name\x18\x02 \x02(\t\x12\r\n\x05\x65mail\x18\x03 \x01(\t\x12\x0f\n\x07\x66riends\x18\x04 \x03(\t') 17 | 18 | 19 | 20 | 21 | _STUDENT = _descriptor.Descriptor( 22 | name='Student', 23 | full_name='Student', 24 | filename=None, 25 | file=DESCRIPTOR, 26 | containing_type=None, 27 | fields=[ 28 | _descriptor.FieldDescriptor( 29 | name='id', full_name='Student.id', index=0, 30 | number=1, type=5, cpp_type=1, label=2, 31 | has_default_value=False, default_value=0, 32 | message_type=None, enum_type=None, containing_type=None, 33 | is_extension=False, extension_scope=None, 34 | options=None), 35 | _descriptor.FieldDescriptor( 36 | name='name', full_name='Student.name', index=1, 37 | number=2, type=9, cpp_type=9, label=2, 38 | has_default_value=False, default_value=unicode("", "utf-8"), 39 | message_type=None, enum_type=None, containing_type=None, 40 | is_extension=False, extension_scope=None, 41 | options=None), 42 | _descriptor.FieldDescriptor( 43 | name='email', full_name='Student.email', index=2, 44 | number=3, type=9, cpp_type=9, label=1, 45 | has_default_value=False, default_value=unicode("", "utf-8"), 46 | message_type=None, enum_type=None, containing_type=None, 47 | is_extension=False, extension_scope=None, 48 | options=None), 49 | _descriptor.FieldDescriptor( 50 | name='friends', full_name='Student.friends', index=3, 51 | number=4, type=9, cpp_type=9, label=3, 52 | has_default_value=False, default_value=[], 53 | message_type=None, enum_type=None, containing_type=None, 54 | is_extension=False, extension_scope=None, 55 | options=None), 56 | ], 57 | extensions=[ 58 | ], 59 | nested_types=[], 60 | enum_types=[ 61 | ], 62 | options=None, 63 | is_extendable=False, 64 | extension_ranges=[], 65 | serialized_start=20, 66 | serialized_end=87, 67 | ) 68 | 69 | DESCRIPTOR.message_types_by_name['Student'] = _STUDENT 70 | 71 | class Student(_message.Message): 72 | __metaclass__ = _reflection.GeneratedProtocolMessageType 73 | DESCRIPTOR = _STUDENT 74 | 75 | # @@protoc_insertion_point(class_scope:Student) 76 | 77 | 78 | # @@protoc_insertion_point(module_scope) 79 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson05; 2 | 3 | import java.io.DataInputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | import java.net.Socket; 7 | import java.util.List; 8 | 9 | /** 10 | * Created by wucao on 17/2/27. 11 | */ 12 | public class TcpClient { 13 | 14 | public static void main(String[] args) throws IOException { 15 | 16 | Socket socket = null; 17 | DataOutputStream out = null; 18 | DataInputStream in = null; 19 | 20 | try { 21 | 22 | socket = new Socket("localhost", 8080); 23 | out = new DataOutputStream(socket.getOutputStream()); 24 | in = new DataInputStream(socket.getInputStream()); 25 | 26 | // 创建一个Student传给服务器 27 | StudentMsg.Student.Builder builder = StudentMsg.Student.newBuilder(); 28 | builder.setId(1); 29 | builder.setName("客户端"); 30 | builder.setEmail("xxg@163.com"); 31 | builder.addFriends("A"); 32 | builder.addFriends("B"); 33 | StudentMsg.Student student = builder.build(); 34 | byte[] outputBytes = student.toByteArray(); // Student转成字节码 35 | out.writeInt(outputBytes.length); // write header 36 | out.write(outputBytes); // write body 37 | out.flush(); 38 | 39 | // 获取服务器传过来的Student 40 | int bodyLength = in.readInt(); // read header 41 | byte[] bodyBytes = new byte[bodyLength]; 42 | in.readFully(bodyBytes); // read body 43 | StudentMsg.Student student2 = StudentMsg.Student.parseFrom(bodyBytes); // body字节码解析成Student 44 | System.out.println("Header:" + bodyLength); 45 | System.out.println("Body:"); 46 | System.out.println("ID:" + student2.getId()); 47 | System.out.println("Name:" + student2.getName()); 48 | System.out.println("Email:" + student2.getEmail()); 49 | System.out.println("Friends:"); 50 | List friends = student2.getFriendsList(); 51 | for(String friend : friends) { 52 | System.out.println(friend); 53 | } 54 | 55 | } finally { 56 | // 关闭连接 57 | in.close(); 58 | out.close(); 59 | socket.close(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson05/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from struct import pack, unpack 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet.protocol import Protocol 6 | from twisted.internet import reactor 7 | import StudentMsg_pb2 8 | 9 | # protobuf编码、解码器 10 | class ProtobufProtocol(Protocol): 11 | 12 | # 用于暂时存放接收到的数据 13 | _buffer = b"" 14 | 15 | def dataReceived(self, data): 16 | # 上次未处理的数据加上本次接收到的数据 17 | self._buffer = self._buffer + data 18 | # 一直循环直到新的消息没有接收完整 19 | while True: 20 | # 如果header接收完整 21 | if len(self._buffer) >= 4: 22 | # header部分,按大字节序转int,获取body长度 23 | length, = unpack(">I", self._buffer[0:4]) 24 | # 如果body接收完整 25 | if len(self._buffer) >= 4 + length: 26 | # body部分,protobuf字节码 27 | packet = self._buffer[4:4 + length] 28 | 29 | # protobuf字节码转成Student对象 30 | student = StudentMsg_pb2.Student() 31 | student.ParseFromString(packet) 32 | 33 | # 调用protobufReceived传入Student对象 34 | self.protobufReceived(student) 35 | 36 | # 去掉_buffer中已经处理的消息部分 37 | self._buffer = self._buffer[4 + length:] 38 | else: 39 | break; 40 | else: 41 | break; 42 | 43 | def protobufReceived(self, student): 44 | raise NotImplementedError 45 | 46 | def sendProtobuf(self, student): 47 | # Student对象转为protobuf字节码 48 | data = student.SerializeToString() 49 | # 添加Header前缀指定protobuf字节码长度 50 | self.transport.write(pack(">I", len(data)) + data) 51 | 52 | # 逻辑代码 53 | class TcpServerHandle(ProtobufProtocol): 54 | 55 | # 实现ProtobufProtocol提供的protobufReceived 56 | def protobufReceived(self, student): 57 | 58 | # 将接收到的Student输出 59 | print 'ID:' + str(student.id) 60 | print 'Name:' + student.name 61 | print 'Email:' + student.email 62 | print 'Friends:' 63 | for friend in student.friends: 64 | print friend 65 | 66 | # 创建一个Student并发送给客户端 67 | student2 = StudentMsg_pb2.Student() 68 | student2.id = 9 69 | student2.name = '服务器'.decode('UTF-8') # 中文需要转成UTF-8字符串 70 | student2.email = '123@abc.com' 71 | student2.friends.append('X') 72 | student2.friends.append('Y') 73 | self.sendProtobuf(student2) 74 | 75 | factory = Factory() 76 | factory.protocol = TcpServerHandle 77 | reactor.listenTCP(8080, factory) 78 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson06/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson06; 2 | 3 | import org.apache.mina.core.service.IoAcceptor; 4 | import org.apache.mina.core.service.IoHandlerAdapter; 5 | import org.apache.mina.core.session.IoSession; 6 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 7 | import org.apache.mina.filter.codec.textline.TextLineCodecFactory; 8 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 9 | 10 | import java.io.IOException; 11 | import java.net.InetSocketAddress; 12 | import java.nio.charset.Charset; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class MinaServer { 18 | 19 | public static void main(String[] args) throws IOException { 20 | IoAcceptor acceptor = new NioSocketAcceptor(); 21 | 22 | acceptor.getFilterChain().addLast("codec", 23 | new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n"))); 24 | 25 | acceptor.setHandler(new TcpServerHandle()); 26 | acceptor.bind(new InetSocketAddress(8080)); 27 | } 28 | } 29 | 30 | class TcpServerHandle extends IoHandlerAdapter { 31 | 32 | @Override 33 | public void exceptionCaught(IoSession session, Throwable cause) 34 | throws Exception { 35 | cause.printStackTrace(); 36 | } 37 | 38 | // 接收到新的数据 39 | @Override 40 | public void messageReceived(IoSession session, Object message) 41 | throws Exception { 42 | 43 | int counter = 1; 44 | 45 | // 第一次请求,创建session中的counter 46 | if(session.getAttribute("counter") == null) { 47 | session.setAttribute("counter", 1); 48 | } else { 49 | // 获取session中的counter,加1后再存入session 50 | counter = (Integer) session.getAttribute("counter"); 51 | counter++; 52 | session.setAttribute("counter", counter); 53 | } 54 | 55 | String line = (String) message; 56 | System.out.println("第" + counter + "次请求:" + line); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson06/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson06; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LineBasedFrameDecoder; 9 | import io.netty.handler.codec.string.StringDecoder; 10 | import io.netty.util.CharsetUtil; 11 | 12 | /** 13 | * Created by wucao on 17/2/27. 14 | */ 15 | public class NettyServer { 16 | 17 | public static void main(String[] args) throws InterruptedException { 18 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 19 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 20 | try { 21 | ServerBootstrap b = new ServerBootstrap(); 22 | b.group(bossGroup, workerGroup) 23 | .channel(NioServerSocketChannel.class) 24 | .childHandler(new ChannelInitializer() { 25 | @Override 26 | public void initChannel(SocketChannel ch) throws Exception { 27 | ChannelPipeline pipeline = ch.pipeline(); 28 | pipeline.addLast(new LineBasedFrameDecoder(80)); 29 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 30 | pipeline.addLast(new TcpServerHandler()); // 针对每个TCP连接创建一个新的ChannelHandler实例 31 | } 32 | }); 33 | ChannelFuture f = b.bind(8080).sync(); 34 | f.channel().closeFuture().sync(); 35 | } finally { 36 | workerGroup.shutdownGracefully(); 37 | bossGroup.shutdownGracefully(); 38 | } 39 | } 40 | } 41 | 42 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 43 | 44 | // 连接相关的信息直接保存在TcpServerHandler的成员变量中 45 | private int counter = 0; 46 | 47 | @Override 48 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 49 | 50 | counter++; 51 | 52 | String line = (String) msg; 53 | System.out.println("第" + counter + "次请求:" + line); 54 | } 55 | 56 | @Override 57 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 58 | cause.printStackTrace(); 59 | ctx.close(); 60 | } 61 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson06/NettyServer2.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson06; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LineBasedFrameDecoder; 9 | import io.netty.handler.codec.string.StringDecoder; 10 | import io.netty.util.Attribute; 11 | import io.netty.util.AttributeKey; 12 | import io.netty.util.CharsetUtil; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class NettyServer2 { 18 | 19 | public static void main(String[] args) throws InterruptedException { 20 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 21 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 22 | try { 23 | ServerBootstrap b = new ServerBootstrap(); 24 | b.group(bossGroup, workerGroup) 25 | .channel(NioServerSocketChannel.class) 26 | .childHandler(new ChannelInitializer() { 27 | 28 | private TcpServerHandler2 tcpServerHandler = new TcpServerHandler2(); 29 | 30 | @Override 31 | public void initChannel(SocketChannel ch) throws Exception { 32 | ChannelPipeline pipeline = ch.pipeline(); 33 | pipeline.addLast(new LineBasedFrameDecoder(80)); 34 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 35 | pipeline.addLast(tcpServerHandler); // 多个连接使用同一个ChannelHandler实例 36 | } 37 | }); 38 | ChannelFuture f = b.bind(8080).sync(); 39 | f.channel().closeFuture().sync(); 40 | } finally { 41 | workerGroup.shutdownGracefully(); 42 | bossGroup.shutdownGracefully(); 43 | } 44 | } 45 | } 46 | 47 | @ChannelHandler.Sharable // 多个连接使用同一个ChannelHandler,要加上@Sharable注解 48 | class TcpServerHandler2 extends ChannelInboundHandlerAdapter { 49 | 50 | private AttributeKey attributeKey = AttributeKey.valueOf("counter"); 51 | 52 | @Override 53 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 54 | 55 | Attribute attribute = ctx.attr(attributeKey); 56 | 57 | int counter = 1; 58 | 59 | if(attribute.get() == null) { 60 | attribute.set(1); 61 | } else { 62 | counter = attribute.get(); 63 | counter++; 64 | attribute.set(counter); 65 | } 66 | 67 | String line = (String) msg; 68 | System.out.println("第" + counter + "次请求:" + line); 69 | } 70 | 71 | @Override 72 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 73 | cause.printStackTrace(); 74 | ctx.close(); 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson06/TcpClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson06; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.net.Socket; 6 | 7 | /** 8 | * Created by wucao on 17/2/27. 9 | */ 10 | public class TcpClient { 11 | 12 | public static void main(String[] args) throws IOException, InterruptedException { 13 | 14 | // 3次TCP连接,每个连接发送2个请求数据 15 | for(int i = 0; i < 3; i++) { 16 | 17 | 18 | Socket socket = null; 19 | OutputStream out = null; 20 | 21 | try { 22 | 23 | socket = new Socket("localhost", 8080); 24 | out = socket.getOutputStream(); 25 | 26 | // 第一次请求服务器 27 | String lines1 = "Hello\r\n"; 28 | byte[] outputBytes1 = lines1.getBytes("UTF-8"); 29 | out.write(outputBytes1); 30 | out.flush(); 31 | 32 | // 第二次请求服务器 33 | String lines2 = "World\r\n"; 34 | byte[] outputBytes2 = lines2.getBytes("UTF-8"); 35 | out.write(outputBytes2); 36 | out.flush(); 37 | 38 | } finally { 39 | // 关闭连接 40 | out.close(); 41 | socket.close(); 42 | } 43 | 44 | Thread.sleep(1000); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson06/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.protocols.basic import LineOnlyReceiver 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor 6 | 7 | class TcpServerHandle(LineOnlyReceiver): 8 | 9 | # 连接相关的信息直接保存为Protocol继承类TcpServerHandle的属性 10 | counter = 0; 11 | 12 | def lineReceived(self, data): 13 | self.counter += 1 14 | print "第" + str(self.counter) + "次请求:" + data 15 | 16 | factory = Factory() 17 | factory.protocol = TcpServerHandle 18 | reactor.listenTCP(8080, factory) 19 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson07/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson07; 2 | 3 | import org.apache.mina.core.IoUtil; 4 | import org.apache.mina.core.service.IoAcceptor; 5 | import org.apache.mina.core.service.IoHandlerAdapter; 6 | import org.apache.mina.core.session.IoSession; 7 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 8 | import org.apache.mina.filter.codec.textline.TextLineCodecFactory; 9 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 10 | 11 | import java.io.IOException; 12 | import java.net.InetSocketAddress; 13 | import java.nio.charset.Charset; 14 | import java.util.Collection; 15 | 16 | /** 17 | * Created by wucao on 17/2/27. 18 | */ 19 | public class MinaServer { 20 | 21 | public static void main(String[] args) throws IOException { 22 | IoAcceptor acceptor = new NioSocketAcceptor(); 23 | 24 | acceptor.getFilterChain().addLast("codec", 25 | new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n"))); 26 | 27 | acceptor.setHandler(new TcpServerHandle()); 28 | acceptor.bind(new InetSocketAddress(8080)); 29 | } 30 | } 31 | 32 | class TcpServerHandle extends IoHandlerAdapter { 33 | 34 | @Override 35 | public void exceptionCaught(IoSession session, Throwable cause) 36 | throws Exception { 37 | cause.printStackTrace(); 38 | } 39 | 40 | @Override 41 | public void messageReceived(IoSession session, Object message) 42 | throws Exception { 43 | 44 | // 获取所有正在连接的IoSession 45 | Collection sessions = session.getService().getManagedSessions().values(); 46 | 47 | // 将消息写到所有IoSession 48 | IoUtil.broadcast(message, sessions); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson07/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson07; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.group.ChannelGroup; 6 | import io.netty.channel.group.DefaultChannelGroup; 7 | import io.netty.channel.nio.NioEventLoopGroup; 8 | import io.netty.channel.socket.SocketChannel; 9 | import io.netty.channel.socket.nio.NioServerSocketChannel; 10 | import io.netty.handler.codec.LineBasedFrameDecoder; 11 | import io.netty.handler.codec.string.StringDecoder; 12 | import io.netty.handler.codec.string.StringEncoder; 13 | import io.netty.util.CharsetUtil; 14 | import io.netty.util.concurrent.GlobalEventExecutor; 15 | 16 | /** 17 | * Created by wucao on 17/2/27. 18 | */ 19 | public class NettyServer { 20 | 21 | public static void main(String[] args) throws InterruptedException { 22 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 23 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 24 | try { 25 | ServerBootstrap b = new ServerBootstrap(); 26 | b.group(bossGroup, workerGroup) 27 | .channel(NioServerSocketChannel.class) 28 | .childHandler(new ChannelInitializer() { 29 | @Override 30 | public void initChannel(SocketChannel ch) throws Exception { 31 | ChannelPipeline pipeline = ch.pipeline(); 32 | pipeline.addLast(new LineBasedFrameDecoder(80)); 33 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 34 | pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); 35 | pipeline.addLast(new TcpServerHandler()); 36 | } 37 | }); 38 | ChannelFuture f = b.bind(8080).sync(); 39 | f.channel().closeFuture().sync(); 40 | } finally { 41 | workerGroup.shutdownGracefully(); 42 | bossGroup.shutdownGracefully(); 43 | } 44 | } 45 | } 46 | 47 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 48 | 49 | // ChannelGroup用于保存所有连接的客户端,注意要用static来保证只有一个ChannelGroup实例,否则每new一个TcpServerHandler都会创建一个ChannelGroup 50 | private static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); 51 | 52 | @Override 53 | public void channelActive(ChannelHandlerContext ctx) { 54 | channels.add(ctx.channel()); // 将新的连接加入到ChannelGroup,当连接断开ChannelGroup会自动移除对应的Channel 55 | } 56 | 57 | @Override 58 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 59 | channels.writeAndFlush(msg + "\r\n"); // 接收到消息后,将消息发送到ChannelGroup中的所有客户端 60 | } 61 | 62 | @Override 63 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 64 | // cause.printStackTrace(); 暂时把异常打印注释掉,因为PublishClient发布一条消息后会立即断开连接,而服务器也会向PublishClient发送消息,所以会抛出异常 65 | ctx.close(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson07/PublishClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson07; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.net.Socket; 6 | 7 | /** 8 | * Created by wucao on 17/2/27. 9 | */ 10 | public class PublishClient { 11 | 12 | public static void main(String[] args) throws IOException { 13 | 14 | Socket socket = null; 15 | OutputStream out = null; 16 | 17 | try { 18 | 19 | socket = new Socket("localhost", 8080); 20 | out = socket.getOutputStream(); 21 | out.write("Hello\r\n".getBytes()); // 发布信息到服务器 22 | out.flush(); 23 | 24 | } finally { 25 | // 关闭连接 26 | out.close(); 27 | socket.close(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson07/SubscribeClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson07; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.net.Socket; 7 | 8 | /** 9 | * Created by wucao on 17/2/27. 10 | */ 11 | public class SubscribeClient { 12 | 13 | public static void main(String[] args) throws IOException { 14 | 15 | Socket socket = null; 16 | BufferedReader in = null; 17 | 18 | try { 19 | 20 | socket = new Socket("localhost", 8080); 21 | in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 22 | 23 | while (true) { 24 | String line = in.readLine(); // 阻塞等待服务器发布的消息 25 | if(line == null) { 26 | break; 27 | } 28 | System.out.println(line); 29 | } 30 | 31 | } finally { 32 | // 关闭连接 33 | in.close(); 34 | socket.close(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson07/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.protocols.basic import LineOnlyReceiver 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor 6 | 7 | class TcpServerHandle(LineOnlyReceiver): 8 | 9 | def __init__(self, factory): 10 | self.factory = factory 11 | 12 | def connectionMade(self): 13 | self.factory.clients.add(self) # 新连接添加连接对应的Protocol实例到clients 14 | 15 | def connectionLost(self, reason): 16 | self.factory.clients.remove(self) # 连接断开移除连接对应的Protocol实例 17 | 18 | def lineReceived(self, line): 19 | # 遍历所有的连接,发送数据 20 | for c in self.factory.clients: 21 | c.sendLine(line) 22 | 23 | class TcpServerFactory(Factory): 24 | def __init__(self): 25 | self.clients = set() # set集合用于保存所有连接到服务器的客户端 26 | 27 | def buildProtocol(self, addr): 28 | return TcpServerHandle(self) 29 | 30 | reactor.listenTCP(8080, TcpServerFactory()) 31 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson08/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson08; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.service.IoAcceptor; 5 | import org.apache.mina.core.service.IoHandlerAdapter; 6 | import org.apache.mina.core.session.IoSession; 7 | import org.apache.mina.http.HttpServerCodec; 8 | import org.apache.mina.http.api.*; 9 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 10 | 11 | import java.io.IOException; 12 | import java.net.InetSocketAddress; 13 | import java.net.URLDecoder; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | /** 18 | * Created by wucao on 17/2/27. 19 | */ 20 | public class MinaServer { 21 | 22 | public static void main(String[] args) throws IOException { 23 | IoAcceptor acceptor = new NioSocketAcceptor(); 24 | acceptor.getFilterChain().addLast("codec", new HttpServerCodec()); 25 | acceptor.setHandler(new HttpServerHandle()); 26 | acceptor.bind(new InetSocketAddress(8080)); 27 | } 28 | } 29 | 30 | class HttpServerHandle extends IoHandlerAdapter { 31 | 32 | @Override 33 | public void exceptionCaught(IoSession session, Throwable cause) 34 | throws Exception { 35 | cause.printStackTrace(); 36 | } 37 | 38 | @Override 39 | public void messageReceived(IoSession session, Object message) 40 | throws Exception { 41 | 42 | if (message instanceof HttpRequest) { 43 | 44 | // 请求,解码器将请求转换成HttpRequest对象 45 | HttpRequest request = (HttpRequest) message; 46 | 47 | // 获取请求参数 48 | String name = request.getParameter("name"); 49 | if(name == null) { 50 | name = "World"; 51 | } 52 | name = URLDecoder.decode(name, "UTF-8"); 53 | 54 | // 响应HTML 55 | String responseHtml = "Hello, " + name + ""; 56 | byte[] responseBytes = responseHtml.getBytes("UTF-8"); 57 | int contentLength = responseBytes.length; 58 | 59 | // 构造HttpResponse对象,HttpResponse只包含响应的status line和header部分 60 | Map headers = new HashMap(); 61 | headers.put("Content-Type", "text/html; charset=utf-8"); 62 | headers.put("Content-Length", Integer.toString(contentLength)); 63 | HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SUCCESS_OK, headers); 64 | 65 | // 响应BODY 66 | IoBuffer responseIoBuffer = IoBuffer.allocate(contentLength); 67 | responseIoBuffer.put(responseBytes); 68 | responseIoBuffer.flip(); 69 | 70 | session.write(response); // 响应的status line和header部分 71 | session.write(responseIoBuffer); // 响应body部分 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson08/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson08; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.*; 6 | import io.netty.channel.nio.NioEventLoopGroup; 7 | import io.netty.channel.socket.SocketChannel; 8 | import io.netty.channel.socket.nio.NioServerSocketChannel; 9 | import io.netty.handler.codec.http.*; 10 | 11 | import java.io.UnsupportedEncodingException; 12 | 13 | /** 14 | * Created by wucao on 17/2/27. 15 | */ 16 | public class NettyServer { 17 | 18 | public static void main(String[] args) throws InterruptedException { 19 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 20 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 21 | try { 22 | ServerBootstrap b = new ServerBootstrap(); 23 | b.group(bossGroup, workerGroup) 24 | .channel(NioServerSocketChannel.class) 25 | .childHandler(new ChannelInitializer() { 26 | @Override 27 | public void initChannel(SocketChannel ch) throws Exception { 28 | ChannelPipeline pipeline = ch.pipeline(); 29 | pipeline.addLast(new HttpServerCodec()); 30 | pipeline.addLast(new HttpServerHandler()); 31 | } 32 | }); 33 | ChannelFuture f = b.bind(8080).sync(); 34 | f.channel().closeFuture().sync(); 35 | } finally { 36 | workerGroup.shutdownGracefully(); 37 | bossGroup.shutdownGracefully(); 38 | } 39 | } 40 | } 41 | 42 | class HttpServerHandler extends ChannelInboundHandlerAdapter { 43 | 44 | @Override 45 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { 46 | 47 | if (msg instanceof HttpRequest) { 48 | 49 | // 请求,解码器将请求转换成HttpRequest对象 50 | HttpRequest request = (HttpRequest) msg; 51 | 52 | // 获取请求参数 53 | QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri()); 54 | String name = "World"; 55 | if(queryStringDecoder.parameters().get("name") != null) { 56 | name = queryStringDecoder.parameters().get("name").get(0); 57 | } 58 | 59 | // 响应HTML 60 | String responseHtml = "Hello, " + name + ""; 61 | byte[] responseBytes = responseHtml.getBytes("UTF-8"); 62 | int contentLength = responseBytes.length; 63 | 64 | // 构造FullHttpResponse对象,FullHttpResponse包含message body 65 | FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseBytes)); 66 | response.headers().set("Content-Type", "text/html; charset=utf-8"); 67 | response.headers().set("Content-Length", Integer.toString(contentLength)); 68 | 69 | ctx.writeAndFlush(response); 70 | } 71 | } 72 | 73 | @Override 74 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 75 | cause.printStackTrace(); 76 | ctx.close(); 77 | } 78 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson08/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.web import server, resource 4 | from twisted.internet import reactor 5 | 6 | class MainResource(resource.Resource): 7 | 8 | isLeaf = True 9 | 10 | # 用于处理GET类型请求 11 | def render_GET(self, request): 12 | 13 | # name参数 14 | name = 'World' 15 | if request.args.has_key('name'): 16 | name = request.args['name'][0] 17 | 18 | # 设置响应编码 19 | request.responseHeaders.addRawHeader("Content-Type", "text/html; charset=utf-8") 20 | 21 | # 响应的内容直接返回 22 | return "Hello, " + name + "" 23 | 24 | 25 | site = server.Site(MainResource()) 26 | reactor.listenTCP(8080, site) 27 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson11; 2 | 3 | import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 4 | import org.apache.mina.core.service.IoAcceptor; 5 | import org.apache.mina.core.service.IoHandlerAdapter; 6 | import org.apache.mina.core.session.IoSession; 7 | import org.apache.mina.filter.codec.ProtocolCodecFilter; 8 | import org.apache.mina.filter.codec.textline.TextLineCodecFactory; 9 | import org.apache.mina.filter.ssl.SslFilter; 10 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 11 | 12 | import javax.net.ssl.KeyManagerFactory; 13 | import javax.net.ssl.SSLContext; 14 | import java.io.File; 15 | import java.io.FileInputStream; 16 | import java.io.InputStream; 17 | import java.net.InetSocketAddress; 18 | import java.nio.charset.Charset; 19 | import java.nio.file.Files; 20 | import java.security.*; 21 | import java.security.cert.Certificate; 22 | import java.security.cert.CertificateFactory; 23 | import java.security.spec.PKCS8EncodedKeySpec; 24 | 25 | /** 26 | * Created by wucao on 17/2/27. 27 | */ 28 | public class MinaServer { 29 | 30 | public static void main(String[] args) throws Exception { 31 | 32 | 33 | String certPath = "/Users/wucao/Desktop/ssl/cert.crt"; // 证书 34 | String privateKeyPath = "/Users/wucao/Desktop/ssl/private.der"; // 私钥 35 | 36 | // 证书 37 | // https://docs.oracle.com/javase/7/docs/api/java/security/cert/X509Certificate.html 38 | InputStream inStream = null; 39 | Certificate certificate = null; 40 | try { 41 | inStream = new FileInputStream(certPath); 42 | CertificateFactory cf = CertificateFactory.getInstance("X.509"); 43 | certificate = cf.generateCertificate(inStream); 44 | } finally { 45 | if (inStream != null) { 46 | inStream.close(); 47 | } 48 | } 49 | 50 | // 私钥 51 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Files.readAllBytes(new File(privateKeyPath).toPath())); 52 | PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); 53 | 54 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 55 | ks.load(null, null); 56 | Certificate[] certificates = {certificate}; 57 | ks.setKeyEntry("key", privateKey, "".toCharArray(), certificates); 58 | 59 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 60 | kmf.init(ks, "".toCharArray()); 61 | 62 | SSLContext sslContext = SSLContext.getInstance("TLS"); 63 | sslContext.init(kmf.getKeyManagers(), null, null); 64 | 65 | IoAcceptor acceptor = new NioSocketAcceptor(); 66 | DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 67 | chain.addLast("ssl", new SslFilter(sslContext)); // SslFilter需要放在最前面 68 | chain.addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"), "\r\n", "\r\n"))); 69 | acceptor.setHandler(new TcpServerHandle()); 70 | acceptor.bind(new InetSocketAddress(8080)); 71 | } 72 | } 73 | 74 | 75 | class TcpServerHandle extends IoHandlerAdapter { 76 | 77 | @Override 78 | public void exceptionCaught(IoSession session, Throwable cause) 79 | throws Exception { 80 | cause.printStackTrace(); 81 | } 82 | 83 | @Override 84 | public void messageReceived(IoSession session, Object message) 85 | throws Exception { 86 | String line = (String) message; 87 | System.out.println("messageReceived:" + line); 88 | } 89 | 90 | @Override 91 | public void sessionCreated(IoSession session) throws Exception { 92 | System.out.println("sessionCreated"); 93 | } 94 | 95 | @Override 96 | public void sessionClosed(IoSession session) throws Exception { 97 | System.out.println("sessionClosed"); 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson11; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.LineBasedFrameDecoder; 9 | import io.netty.handler.codec.string.StringDecoder; 10 | import io.netty.handler.ssl.SslContext; 11 | import io.netty.handler.ssl.SslContextBuilder; 12 | import io.netty.handler.ssl.SslHandler; 13 | import io.netty.util.CharsetUtil; 14 | 15 | import javax.net.ssl.SSLException; 16 | import java.io.File; 17 | 18 | /** 19 | * Created by wucao on 17/2/27. 20 | */ 21 | public class NettyServer { 22 | 23 | public static void main(String[] args) throws InterruptedException, SSLException { 24 | 25 | File certificate = new File("/Users/wucao/Desktop/ssl/cert.crt"); // 证书 26 | File privateKey = new File("/Users/wucao/Desktop/ssl/private.pem"); // 私钥 27 | final SslContext sslContext = SslContextBuilder.forServer(certificate, privateKey).build(); 28 | 29 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 30 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 31 | try { 32 | ServerBootstrap b = new ServerBootstrap(); 33 | b.group(bossGroup, workerGroup) 34 | .channel(NioServerSocketChannel.class) 35 | .childHandler(new ChannelInitializer() { 36 | @Override 37 | public void initChannel(SocketChannel ch) 38 | throws Exception { 39 | ChannelPipeline pipeline = ch.pipeline(); 40 | 41 | // SslHandler要放在最前面 42 | SslHandler sslHandler = sslContext.newHandler(ch.alloc()); 43 | pipeline.addLast(sslHandler); 44 | 45 | pipeline.addLast(new LineBasedFrameDecoder(80)); 46 | pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); 47 | 48 | pipeline.addLast(new TcpServerHandler()); 49 | } 50 | }); 51 | ChannelFuture f = b.bind(8080).sync(); 52 | f.channel().closeFuture().sync(); 53 | } finally { 54 | workerGroup.shutdownGracefully(); 55 | bossGroup.shutdownGracefully(); 56 | } 57 | } 58 | 59 | } 60 | 61 | class TcpServerHandler extends ChannelInboundHandlerAdapter { 62 | 63 | @Override 64 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 65 | String line = (String) msg; 66 | System.out.println("channelRead:" + line); 67 | } 68 | 69 | @Override 70 | public void channelActive(ChannelHandlerContext ctx) { 71 | System.out.println("channelActive"); 72 | } 73 | 74 | @Override 75 | public void channelInactive(ChannelHandlerContext ctx) { 76 | System.out.println("channelInactive"); 77 | } 78 | 79 | @Override 80 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 81 | cause.printStackTrace(); 82 | ctx.close(); 83 | } 84 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/SslClient.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson11; 2 | 3 | import javax.net.ssl.SSLContext; 4 | import javax.net.ssl.SSLSocketFactory; 5 | import javax.net.ssl.TrustManagerFactory; 6 | import java.io.FileInputStream; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | import java.net.Socket; 10 | import java.security.KeyStore; 11 | import java.security.cert.Certificate; 12 | import java.security.cert.CertificateFactory; 13 | 14 | /** 15 | * Created by wucao on 17/2/27. 16 | */ 17 | public class SslClient { 18 | 19 | public static void main(String args[]) throws Exception { 20 | 21 | // 客户端信任改证书,将用于校验服务器传过来的证书的合法性 22 | String certPath = "/Users/wucao/Desktop/ssl/cert.crt"; 23 | InputStream inStream = null; 24 | Certificate certificate = null; 25 | try { 26 | inStream = new FileInputStream(certPath); 27 | CertificateFactory cf = CertificateFactory.getInstance("X.509"); 28 | certificate = cf.generateCertificate(inStream); 29 | } finally { 30 | if (inStream != null) { 31 | inStream.close(); 32 | } 33 | } 34 | 35 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 36 | ks.load(null, null); 37 | ks.setCertificateEntry("cert", certificate); 38 | 39 | TrustManagerFactory tmf = TrustManagerFactory.getInstance("sunx509"); 40 | tmf.init(ks); 41 | 42 | SSLContext sslContext = SSLContext.getInstance("TLS"); 43 | sslContext.init(null, tmf.getTrustManagers(), null); 44 | 45 | SSLSocketFactory socketFactory = sslContext.getSocketFactory(); 46 | 47 | Socket socket = null; 48 | OutputStream out = null; 49 | 50 | try { 51 | 52 | socket = socketFactory.createSocket("localhost", 8080); 53 | out = socket.getOutputStream(); 54 | 55 | // 请求服务器 56 | String lines = "床前明月光\r\n疑是地上霜\r\n举头望明月\r\n低头思故乡\r\n"; 57 | byte[] outputBytes = lines.getBytes("UTF-8"); 58 | out.write(outputBytes); 59 | out.flush(); 60 | 61 | } finally { 62 | // 关闭连接 63 | out.close(); 64 | socket.close(); 65 | } 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.protocols.basic import LineOnlyReceiver 4 | from twisted.internet.protocol import Factory 5 | from twisted.internet import reactor, ssl 6 | 7 | sslContext = ssl.DefaultOpenSSLContextFactory( 8 | '/Users/wucao/Desktop/ssl/private.pem', # 私钥 9 | '/Users/wucao/Desktop/ssl/cert.crt', # 证书 10 | ) 11 | 12 | class TcpServerHandle(LineOnlyReceiver): 13 | 14 | def connectionMade(self): 15 | print 'connectionMade' 16 | 17 | def connectionLost(self, reason): 18 | print 'connectionLost' 19 | 20 | def lineReceived(self, data): 21 | print 'lineReceived:' + data 22 | 23 | factory = Factory() 24 | factory.protocol = TcpServerHandle 25 | reactor.listenSSL(8080, factory, sslContext) 26 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/cert.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDXTCCAkWgAwIBAgIJAL/Q3Pur3M2oMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTcwMjI3MDY1NTM5WhcNMTgwMjI3MDY1NTM5WjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEAwQEa7N1qqVriESrcw3jhbo5ta4cDW5uAjzyQzzpUTxzUYYUq3rQjC68c 8 | n7rL1uFzPRX6BM6JqDxg2ygCrECEV2SciGtvl9idFdk6ydBrWJMzHqs21RX9UxKM 9 | bPmQ0wEltUymZ9eTVf4hnV+tEtBixYMavvvLJpkYcXR5aFLvLyJEKAI8SA8Giuzw 10 | U8c87jbdxeEbgR6ch6BHSJhfINMBZaWL2HR4Z72zSP3fKTKubh/tGcU3O/R+sCyz 11 | TTcS/d3wGWmcUwti0lJY26a+YVcKJpOFO2WBmTalYOdRHEH7jsRjdfh5y1eEZnM9 12 | l+DzJgAjgWN/f7LCpUSzTpih85n4HwIDAQABo1AwTjAdBgNVHQ4EFgQUamK3E8bI 13 | N+d5swHZ9IXW8fqGBmMwHwYDVR0jBBgwFoAUamK3E8bIN+d5swHZ9IXW8fqGBmMw 14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAetq9lsBjwXSXubpDRx+g 15 | /qnE7LDqswpb+n7rHj1UFg/HrLUpbJXOVYNAVzx7+uiI6WJyWWZpj2bXuLjIn1zh 16 | VRfNqazfCK6OptHmw95eJRb6+3c5+dWl7PLrCvCUR6xDkFlBWyojjOeY67JIpkNf 17 | XjJyEpNo3VHUbDO3Q1wuYrmU39/wgqxQomxghafAacSdRkILoXnpasMjOV4WWPfK 18 | lvNCnKXhekdEtG+dMzFp5nHq66dYtdNkf/IbbxOvMCNtDq8rgXgWEY6gy6nd7TM5 19 | dy3VvR/Si5EC2/fx5wa50KT5FsQ9UKgXKARKqYR35HnC72r+WPDORIFj15dmqw05 20 | Fg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/private.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wucao/mina-netty-twisted/fb4858b3f743f71e4d0c9931a7fa5f8d9620768d/src/main/java/com/xxg/network/lesson11/private.der -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson11/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBARrs3WqpWuIR 3 | KtzDeOFujm1rhwNbm4CPPJDPOlRPHNRhhSretCMLrxyfusvW4XM9FfoEzomoPGDb 4 | KAKsQIRXZJyIa2+X2J0V2TrJ0GtYkzMeqzbVFf1TEoxs+ZDTASW1TKZn15NV/iGd 5 | X60S0GLFgxq++8smmRhxdHloUu8vIkQoAjxIDwaK7PBTxzzuNt3F4RuBHpyHoEdI 6 | mF8g0wFlpYvYdHhnvbNI/d8pMq5uH+0ZxTc79H6wLLNNNxL93fAZaZxTC2LSUljb 7 | pr5hVwomk4U7ZYGZNqVg51EcQfuOxGN1+HnLV4Rmcz2X4PMmACOBY39/ssKlRLNO 8 | mKHzmfgfAgMBAAECggEAWcP60unUXvofJN7rmJqTNslViOpdnHDBpV0E+OznI3iE 9 | Kus12iisGBYU2RGXFtT6tRGQnEW3bqDOZ3+/ZoAHTWJFD4nweA5OWUgUeKLQGn00 10 | DHKTaR32GXoKB/E283yYHi+NQcTZCOjOl5RVOefj2Hs2qFcR0FzqKnKCuQvBpQib 11 | B2cMAOdEylnFfuGgrd5OJNmNH+MQLK5+1bLfJ3fzUn50xUjvZOKpRwdW/yjKvZ1n 12 | NqjLgi1/wimPOciGNl1BUTTr/g/vTyla7CDMmrT1ep8E5bYsnaO1ItG4gqhMcXup 13 | XCyYaVv7ii4mXc8DOAYrzZUVr87SiWCyUJkzhlzH2QKBgQDmN8rxRJLSYr3EAwIc 14 | 6FN1/4y+Ye4C/G+h/WsFAWNooJtWy+QfOWeLbZzfqeZfvfhpued4JvfX9yNwQOzh 15 | sQy/l0O9VzBPxibYOCsfMIfTBleAoB7gS5FMZRL04pHLar9oDZHIpHVCWbg2oFee 16 | qUtZ8TUlgqDYjsm2FQsXtIH8iwKBgQDWnmuwXoZGvO/XCczY36hc0lEn2pAM2ewG 17 | MAKJbf8KGydBikLKD4nDoTimjRUC50gzx5tHJAdkyaM/k5PoZGFBLyzoTnUT6WtF 18 | 3ngYvYy4sh+mvKBd/3W8xbfTwrBjho9rMg/lKk6ipmDno+Y18wG0MM6A6tUJtQdV 19 | ZmfnjzTBPQKBgQDhPYUZOPZNUL5JoIfYsJW3xSd2vWmZElJGMyMZ6pnQLBLPgPzY 20 | b9mW2M+7JQd4dO0uw+xr6fRjIDFUCrG4vviyGtTz0vI5mq02rv3BrkG1fWbvObn7 21 | yPOHwvwhC+uJEg/jRiN0IzN2j0FkcMxJN2m5vf05jezA9DL2KvCHaNwksQKBgQCM 22 | BP1TKshF/Fwpmm44C+sm69wguTqD9+VBwC7XhJkA+egpnU+nzm1d4aA5IRBVPZlg 23 | ltiamEnumpLUFq9Hzb2ZrnKI+S7vF7lx8wu9cGUP1r5JpQSnbtRcnU4qbPlxZUfK 24 | cvXl2C1Hdm8AkXDPP8Sbz7/aYdstoxquv8oIS+jqLQKBgBbL7b96PQazxuxDynIP 25 | O4983su+Ggxupw+peJDmxtnPrETqPYT070BDNAjHs8Ct7TOF6aSmvNZpACHk110V 26 | fpZhQnyMzxyYAIgJbNO0MERO3kOxD0G+Mg0HyEXHmq94KKM31B5XG3apqKEVPysa 27 | fbrb1dn738FWXhggS2gxWeQY 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/1_gw2.vsgames.cn_bundle.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFwDCCBKigAwIBAgIQWmo1vJVJq7baijHgx2MhSjANBgkqhkiG9w0BAQsFADCB 3 | lzELMAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs 4 | IEluYy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsT 5 | FERvbWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NM 6 | IENBIC0gRzUwHhcNMTcwMjIxMDAwMDAwWhcNMTgwMjIxMjM1OTU5WjAZMRcwFQYD 7 | VQQDDA5ndzIudnNnYW1lcy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 8 | ggEBAJADNRO0Qm7GJtpEbIZKWJqF5E1IKFNII5PQ/z0nyPOxEsHeOVxmcMNi1CKm 9 | oCnjxO2JR7ow+PO1nRGxZtEDqqJOhiK8SULRrnY2Lviy8Ne+2wO0O/XJqqPy+TFt 10 | 6f2zH+3quBoLRIfKm3soI332xUaw7yoZuyWHnJaaT1bW5zIxB+3qW20mGo8jh1OC 11 | 6L1on9Adr2HSLaAKh8WIQ6FqzrYcoAPJV6yFh+QKToICnNpP6NudBHIXuzwv3xtL 12 | 5VtNZxIxTaBQmoDPxCZ3W7dlqb8R/FlUMgVswQE65wca1s8XeWwAiQBblRhlQqZg 13 | RpjoO5ggOqqa2G3aLIf+6Tx/rYMCAwEAAaOCAoMwggJ/MBkGA1UdEQQSMBCCDmd3 14 | Mi52c2dhbWVzLmNuMAkGA1UdEwQCMAAwYQYDVR0gBFowWDBWBgZngQwBAgEwTDAj 15 | BggrBgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIw 16 | GQwXaHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUbVjHfxrn4T8u 17 | poyXNUK79NM4rD8wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB 18 | BggrBgEFBQcDAjCBmwYIKwYBBQUHAQEEgY4wgYswPAYIKwYBBQUHMAGGMGh0dHA6 19 | Ly90cnVzdGFzaWEyLW9jc3AuZGlnaXRhbGNlcnR2YWxpZGF0aW9uLmNvbTBLBggr 20 | BgEFBQcwAoY/aHR0cDovL3RydXN0YXNpYTItYWlhLmRpZ2l0YWxjZXJ0dmFsaWRh 21 | dGlvbi5jb20vdHJ1c3Rhc2lhZzUuY3J0MIIBBAYKKwYBBAHWeQIEAgSB9QSB8gDw 22 | AHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFaYE4b1AAABAMA 23 | RzBFAiEA3/beRVJaRu+KsxJoTltAKCcY62b+wvIu/0smb0ikLswCIFUeL79iOayc 24 | Sd4/nwFeh8yGdPoZR7O7+ju0utMqPPk+AHYApLkJkLQYWBSHuxOizGdwCjw1mAT5 25 | G9+443fNDsgN3BAAAAFaYE4cDQAABAMARzBFAiEAscUJt3+lpopYGX1rwq5HUgz8 26 | IZ1MjMg9nEIMwu+dU3ICIFcrv6OaKtyLqe23fMfE9JgrgPXjyDw7AEiDLo/JaJ38 27 | MA0GCSqGSIb3DQEBCwUAA4IBAQC0zJunhH+nuDurBEnY5vJ2WiUKgXwDGQmR6Nla 28 | jIHLiLPp03tLRZTiJjmthDaZpoAwskmp8m25kuAPgv3iChDtPg58uMvimeaxH4KA 29 | agDXxh2yPgdr6wm5+9zUO16dbzshbeJf0vj9yD8GP7A71bC9goiAQuC4MiW5kf+J 30 | EhLPFp8maR12ljPb3x/hsjT8jN/9HxBcfuh3dJT6ZnBcGa8c5zOTyP3f22uvoeCo 31 | J6EG9Sk26NG6fYJbb0piu8ejPAMNXc+QCGG1hxb0guxrFOSY+CUPhmlnhjjvOK/5 32 | DCEc8hAINg7X4jmJSHNAv66IZNIK8K67jn6zwo/4B/CRIsXW 33 | -----END CERTIFICATE----- 34 | 35 | 36 | -----BEGIN CERTIFICATE----- 37 | MIIFZTCCBE2gAwIBAgIQOhAOfxCeGsWcxf/2QNXkQjANBgkqhkiG9w0BAQsFADCB 38 | yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL 39 | ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp 40 | U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW 41 | ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 42 | aG9yaXR5IC0gRzUwHhcNMTYwODExMDAwMDAwWhcNMjYwODEwMjM1OTU5WjCBlzEL 43 | MAkGA1UEBhMCQ04xJTAjBgNVBAoTHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIElu 44 | Yy4xHzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxHTAbBgNVBAsTFERv 45 | bWFpbiBWYWxpZGF0ZWQgU1NMMSEwHwYDVQQDExhUcnVzdEFzaWEgRFYgU1NMIENB 46 | IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC39aSJZG/97x3a 47 | 6Qmuc9+MubagegRAVUmFYHTYTs8IKB2pM7wXN7W8mekdZaEgUjDFxvRBK/DhTb7U 48 | 8ONLsKKdT86aOhzbz2noCTn9wPWnGwkg+/4YKg/dPQQdV9tMsSu0cwqInWHxSAkm 49 | AI1hYFC9D7Sf7Hp/5cRcD+dK454YMRzNOGLQnCVI8JEqrz6o9SOvQNTqTcfqt6DC 50 | 0UlXG+MPD1eNPjlzf1Vwaab+VSTgySoC+Ikbq2VsdykeOiGXW/OIiASH7+2LcR05 51 | PmQ7GEOlM8yzoVojFpM8sHz+WxI05ZOPri5+vX3HhHHjWr5432G0dVmgohnZvlVZ 52 | oy8XrlbpAgMBAAGjggF2MIIBcjASBgNVHRMBAf8ECDAGAQH/AgEAMC8GA1UdHwQo 53 | MCYwJKAioCCGHmh0dHA6Ly9zLnN5bWNiLmNvbS9wY2EzLWc1LmNybDAOBgNVHQ8B 54 | Af8EBAMCAQYwLgYIKwYBBQUHAQEEIjAgMB4GCCsGAQUFBzABhhJodHRwOi8vcy5z 55 | eW1jZC5jb20wYQYDVR0gBFowWDBWBgZngQwBAgEwTDAjBggrBgEFBQcCARYXaHR0 56 | cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6Ly9kLnN5 57 | bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMCkGA1Ud 58 | EQQiMCCkHjAcMRowGAYDVQQDExFTeW1hbnRlY1BLSS0yLTYwMTAdBgNVHQ4EFgQU 59 | bVjHfxrn4T8upoyXNUK79NM4rD8wHwYDVR0jBBgwFoAUf9Nlp8Ld7LvwMAnzQzn6 60 | Aq8zMTMwDQYJKoZIhvcNAQELBQADggEBABUphhBbeG7scE3EveIN0dOjXPgwgQi8 61 | I2ZAKYm6DawoGz1lEJVdvFmkyMbP973X80b7mKmn0nNbe1kjA4M0O0hHaMM1ZaEv 62 | 7e9vHEAoGyysMO6HzPWYMkyNxcCV7Nos2Uv4RvLDpQHh7P4Kt6fUU13ipcynrtQD 63 | 1lFUM0yoTzwwFsPu3Pk+94hL58ErqwqJQwxoHMgLIQeMVHeNKcWFy1bddSbIbCWU 64 | Zs6cMxhrra062ZCpDCbxyEaFNGAtYQMqNz55Z/14XgSUONZ/cJTns6QKhpcgTOwB 65 | fnNzRnk+aWreP7osKhXlz4zs+llP7goBDKFOMMtoEXx3YjJCKgpqmBU= 66 | -----END CERTIFICATE----- 67 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/2_gw2.vsgames.cn.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEoAIBAAKCAQEAkAM1E7RCbsYm2kRshkpYmoXkTUgoU0gjk9D/PSfI87ESwd45 3 | XGZww2LUIqagKePE7YlHujD487WdEbFm0QOqok6GIrxJQtGudjYu+LLw177bA7Q7 4 | 9cmqo/L5MW3p/bMf7eq4GgtEh8qbeygjffbFRrDvKhm7JYeclppPVtbnMjEH7epb 5 | bSYajyOHU4LovWif0B2vYdItoAqHxYhDoWrOthygA8lXrIWH5ApOggKc2k/o250E 6 | che7PC/fG0vlW01nEjFNoFCagM/EJndbt2WpvxH8WVQyBWzBATrnBxrWzxd5bACJ 7 | AFuVGGVCpmBGmOg7mCA6qprYbdosh/7pPH+tgwIDAQABAoH/GNh0z8bJr1LVtn0X 8 | kWjs4GaOfMbLg5LD5edTdw7mHHpFl4I/YzGemBb017A88afaJyEIFEIJXAJ5QWmE 9 | fjWjurImx4IJzFK18Vm9FiseYhpgrsLplVNgR+jOFTkL+uPByR+K+PNOCh9qXlUO 10 | dSzzMWmqhBjsW2KKIXF96VLU5aj4QOU+Mws2ideFKu7bkPLQwFwsRxbgLxM9MnpT 11 | 5uziwLNohlm2UGb6wt6DHJDmVTWi+UGNc80IbrAW5Pk1mOxmmwX/2kR/6k22Rq0d 12 | bv+deLyEq+YtbIz709zGGIiIiTvJlV/CeA9s22wHV3uaAru4M+SWIoDEC11NAt2l 13 | xHEpAoGBAMZYjGYP7p55xvnjVcOmB8FgvyUkwV99oQ0WZNlmytOTKlxufthvkzQW 14 | WGgmuFE8jPnEs+beGSy4fXSFB8Vy10fiUeh0FN9LlbPombVTzPUNmHGNIn6vhdoX 15 | NkC3X/zzEAysmg5gmd7wR8yoYIgAHUNrOQmohzJsDkhE5pe+lJv7AoGBALnfkS3P 16 | eqYcxYLBmDpZOfKHeBhp6j2TuSQYJTPcaxzhuFWYnxnRDZtPDgVhmXHgwDZ7CNfI 17 | CzNSHYUovT5pJATvllV39/+z88VlJ7NG7HgBjOvvc0z+midgxE2tllvfT+9B2Gol 18 | JdOd5Ckc2Hcl00ugLQCLs574WN1BKcDHyLYZAoGAZ+ejRSQ7gNGSpv2sxB2KGoew 19 | Gqkyk++gGtcMZccvob6KhnlsAb4Rg0vhbE48aHIr9/xPsjXPQlozfoLiG1GZ7ZJm 20 | DjwhYwiZl/HV8+O+jvFcVr/0viD9Ic7fIO/vXPeIBNu2qKl6cgu10USzrQtCSTs2 21 | WhTrHkL1CG7vzbaM61kCgYAjtFNh9mH7+LjkBiYkxzD/apBiOC47x92fllfHH4cf 22 | 1CghoSCmx+aSN9xcokPkgSTLElU/hfjI0fRDuPCpRW8a158MKfBkmP+xol2+7VfN 23 | MZcNV0DRwHKCL+9lcHvaiAoFzqMwuJQMk17ZmuXl9UkiVNFwMmW9mr0PO0427uma 24 | OQKBgHIPJFFKrS8ncoOLG6mas74eEgx+n/VRC9zeybZ9hPPfItU9xtApbPFf+OsP 25 | /7Jy0/QM/gCqmkE4up5ujS5glmP92VWSpG7k7TN58g2UUsbdiOmebHU6fNoD7OfI 26 | 2XmCweX8Leby0UAiLTXJKFR4nB9rguHLte2o1CeWZNUDDq6Z 27 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/MinaServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson12; 2 | 3 | import org.apache.mina.core.buffer.IoBuffer; 4 | import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder; 5 | import org.apache.mina.core.service.IoAcceptor; 6 | import org.apache.mina.core.service.IoHandlerAdapter; 7 | import org.apache.mina.core.session.IoSession; 8 | import org.apache.mina.filter.ssl.SslFilter; 9 | import org.apache.mina.http.HttpServerCodec; 10 | import org.apache.mina.http.api.*; 11 | import org.apache.mina.transport.socket.nio.NioSocketAcceptor; 12 | 13 | import javax.net.ssl.KeyManagerFactory; 14 | import javax.net.ssl.SSLContext; 15 | import java.io.File; 16 | import java.io.FileInputStream; 17 | import java.io.InputStream; 18 | import java.net.InetSocketAddress; 19 | import java.net.URLDecoder; 20 | import java.nio.file.Files; 21 | import java.security.KeyFactory; 22 | import java.security.KeyStore; 23 | import java.security.PrivateKey; 24 | import java.security.cert.Certificate; 25 | import java.security.cert.CertificateFactory; 26 | import java.security.spec.PKCS8EncodedKeySpec; 27 | import java.util.HashMap; 28 | import java.util.Map; 29 | 30 | /** 31 | * Created by wucao on 17/2/27. 32 | */ 33 | public class MinaServer { 34 | 35 | public static void main(String[] args) throws Exception { 36 | 37 | String certPath = "/Users/wucao/Desktop/https/1_gw2.vsgames.cn_bundle.crt"; // 证书 38 | String privateKeyPath = "/Users/wucao/Desktop/https/private.der"; // 私钥 39 | 40 | // 证书 41 | // https://docs.oracle.com/javase/7/docs/api/java/security/cert/X509Certificate.html 42 | InputStream inStream = null; 43 | Certificate certificate = null; 44 | try { 45 | inStream = new FileInputStream(certPath); 46 | CertificateFactory cf = CertificateFactory.getInstance("X.509"); 47 | certificate = cf.generateCertificate(inStream); 48 | } finally { 49 | if (inStream != null) { 50 | inStream.close(); 51 | } 52 | } 53 | 54 | // 私钥 55 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Files.readAllBytes(new File(privateKeyPath).toPath())); 56 | PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); 57 | 58 | KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 59 | ks.load(null, null); 60 | Certificate[] certificates = {certificate}; 61 | ks.setKeyEntry("key", privateKey, "".toCharArray(), certificates); 62 | 63 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 64 | kmf.init(ks, "".toCharArray()); 65 | 66 | SSLContext sslContext = SSLContext.getInstance("TLS"); 67 | sslContext.init(kmf.getKeyManagers(), null, null); 68 | 69 | 70 | 71 | IoAcceptor acceptor = new NioSocketAcceptor(); 72 | DefaultIoFilterChainBuilder chain = acceptor.getFilterChain(); 73 | chain.addLast("ssl", new SslFilter(sslContext)); // SslFilter + HttpServerCodec实现HTTPS 74 | chain.addLast("codec", new HttpServerCodec()); 75 | acceptor.setHandler(new HttpServerHandle()); 76 | acceptor.bind(new InetSocketAddress(8080)); 77 | } 78 | } 79 | 80 | class HttpServerHandle extends IoHandlerAdapter { 81 | 82 | @Override 83 | public void exceptionCaught(IoSession session, Throwable cause) 84 | throws Exception { 85 | cause.printStackTrace(); 86 | } 87 | 88 | @Override 89 | public void messageReceived(IoSession session, Object message) 90 | throws Exception { 91 | 92 | if (message instanceof HttpRequest) { 93 | 94 | // 请求,解码器将请求转换成HttpRequest对象 95 | HttpRequest request = (HttpRequest) message; 96 | 97 | // 获取请求参数 98 | String name = request.getParameter("name"); 99 | if(name == null) { 100 | name = "World"; 101 | } 102 | name = URLDecoder.decode(name, "UTF-8"); 103 | 104 | // 响应HTML 105 | String responseHtml = "Hello, " + name + ""; 106 | byte[] responseBytes = responseHtml.getBytes("UTF-8"); 107 | int contentLength = responseBytes.length; 108 | 109 | // 构造HttpResponse对象,HttpResponse只包含响应的status line和header部分 110 | Map headers = new HashMap(); 111 | headers.put("Content-Type", "text/html; charset=utf-8"); 112 | headers.put("Content-Length", Integer.toString(contentLength)); 113 | HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SUCCESS_OK, headers); 114 | 115 | // 响应BODY 116 | IoBuffer responseIoBuffer = IoBuffer.allocate(contentLength); 117 | responseIoBuffer.put(responseBytes); 118 | responseIoBuffer.flip(); 119 | 120 | session.write(response); // 响应的status line和header部分 121 | session.write(responseIoBuffer); // 响应body部分 122 | } 123 | } 124 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/NettyServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.lesson12; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.buffer.Unpooled; 5 | import io.netty.channel.*; 6 | import io.netty.channel.nio.NioEventLoopGroup; 7 | import io.netty.channel.socket.SocketChannel; 8 | import io.netty.channel.socket.nio.NioServerSocketChannel; 9 | import io.netty.handler.codec.http.*; 10 | import io.netty.handler.ssl.SslContext; 11 | import io.netty.handler.ssl.SslContextBuilder; 12 | import io.netty.handler.ssl.SslHandler; 13 | 14 | import javax.net.ssl.SSLException; 15 | import java.io.File; 16 | import java.io.UnsupportedEncodingException; 17 | 18 | /** 19 | * Created by wucao on 17/2/27. 20 | */ 21 | public class NettyServer { 22 | 23 | public static void main(String[] args) throws InterruptedException, SSLException { 24 | 25 | File certificate = new File("/Users/wucao/Desktop/https/1_gw2.vsgames.cn_bundle.crt"); // 证书 26 | File privateKey = new File("/Users/wucao/Desktop/https/private.pem"); // 私钥 27 | final SslContext sslContext = SslContextBuilder.forServer(certificate, privateKey).build(); 28 | 29 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 30 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 31 | try { 32 | ServerBootstrap b = new ServerBootstrap(); 33 | b.group(bossGroup, workerGroup) 34 | .channel(NioServerSocketChannel.class) 35 | .childHandler(new ChannelInitializer() { 36 | @Override 37 | public void initChannel(SocketChannel ch) throws Exception { 38 | ChannelPipeline pipeline = ch.pipeline(); 39 | 40 | SslHandler sslHandler = sslContext.newHandler(ch.alloc()); 41 | pipeline.addLast(sslHandler); 42 | 43 | pipeline.addLast(new HttpServerCodec()); 44 | pipeline.addLast(new HttpServerHandler()); 45 | } 46 | }); 47 | ChannelFuture f = b.bind(8080).sync(); 48 | f.channel().closeFuture().sync(); 49 | } finally { 50 | workerGroup.shutdownGracefully(); 51 | bossGroup.shutdownGracefully(); 52 | } 53 | } 54 | } 55 | 56 | class HttpServerHandler extends ChannelInboundHandlerAdapter { 57 | 58 | @Override 59 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { 60 | 61 | if (msg instanceof HttpRequest) { 62 | 63 | // 请求,解码器将请求转换成HttpRequest对象 64 | HttpRequest request = (HttpRequest) msg; 65 | 66 | // 获取请求参数 67 | QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.uri()); 68 | String name = "World"; 69 | if(queryStringDecoder.parameters().get("name") != null) { 70 | name = queryStringDecoder.parameters().get("name").get(0); 71 | } 72 | 73 | // 响应HTML 74 | String responseHtml = "Hello, " + name + ""; 75 | byte[] responseBytes = responseHtml.getBytes("UTF-8"); 76 | int contentLength = responseBytes.length; 77 | 78 | // 构造FullHttpResponse对象,FullHttpResponse包含message body 79 | FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(responseBytes)); 80 | response.headers().set("Content-Type", "text/html; charset=utf-8"); 81 | response.headers().set("Content-Length", Integer.toString(contentLength)); 82 | 83 | ctx.writeAndFlush(response); 84 | } 85 | } 86 | 87 | @Override 88 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 89 | cause.printStackTrace(); 90 | ctx.close(); 91 | } 92 | } -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/TwistedServer.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 –*- 2 | 3 | from twisted.internet import reactor, ssl 4 | from twisted.web import server, resource 5 | 6 | sslContext = ssl.DefaultOpenSSLContextFactory( 7 | '/Users/wucao/Desktop/https/2_gw2.vsgames.cn.key', # 私钥 8 | '/Users/wucao/Desktop/https/1_gw2.vsgames.cn_bundle.crt', # 证书 9 | ) 10 | 11 | class MainResource(resource.Resource): 12 | 13 | isLeaf = True 14 | 15 | # 用于处理GET类型请求 16 | def render_GET(self, request): 17 | 18 | # name参数 19 | name = 'World' 20 | if request.args.has_key('name'): 21 | name = request.args['name'][0] 22 | 23 | # 设置响应编码 24 | request.responseHeaders.addRawHeader("Content-Type", "text/html; charset=utf-8") 25 | 26 | # 响应的内容直接返回 27 | return "Hello, " + name + "" 28 | 29 | 30 | site = server.Site(MainResource()) 31 | reactor.listenSSL(8080, site, sslContext) 32 | reactor.run() -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/private.der: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wucao/mina-netty-twisted/fb4858b3f743f71e4d0c9931a7fa5f8d9620768d/src/main/java/com/xxg/network/lesson12/private.der -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/lesson12/private.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEugIBADANBgkqhkiG9w0BAQEFAASCBKQwggSgAgEAAoIBAQCQAzUTtEJuxiba 3 | RGyGSliaheRNSChTSCOT0P89J8jzsRLB3jlcZnDDYtQipqAp48TtiUe6MPjztZ0R 4 | sWbRA6qiToYivElC0a52Ni74svDXvtsDtDv1yaqj8vkxben9sx/t6rgaC0SHypt7 5 | KCN99sVGsO8qGbslh5yWmk9W1ucyMQft6lttJhqPI4dTgui9aJ/QHa9h0i2gCofF 6 | iEOhas62HKADyVeshYfkCk6CApzaT+jbnQRyF7s8L98bS+VbTWcSMU2gUJqAz8Qm 7 | d1u3Zam/EfxZVDIFbMEBOucHGtbPF3lsAIkAW5UYZUKmYEaY6DuYIDqqmtht2iyH 8 | /uk8f62DAgMBAAECgf8Y2HTPxsmvUtW2fReRaOzgZo58xsuDksPl51N3DuYcekWX 9 | gj9jMZ6YFvTXsDzxp9onIQgUQglcAnlBaYR+NaO6sibHggnMUrXxWb0WKx5iGmCu 10 | wumVU2BH6M4VOQv648HJH4r4804KH2peVQ51LPMxaaqEGOxbYoohcX3pUtTlqPhA 11 | 5T4zCzaJ14Uq7tuQ8tDAXCxHFuAvEz0yelPm7OLAs2iGWbZQZvrC3oMckOZVNaL5 12 | QY1zzQhusBbk+TWY7GabBf/aRH/qTbZGrR1u/514vISr5i1sjPvT3MYYiIiJO8mV 13 | X8J4D2zbbAdXe5oCu7gz5JYigMQLXU0C3aXEcSkCgYEAxliMZg/unnnG+eNVw6YH 14 | wWC/JSTBX32hDRZk2WbK05MqXG5+2G+TNBZYaCa4UTyM+cSz5t4ZLLh9dIUHxXLX 15 | R+JR6HQU30uVs+iZtVPM9Q2YcY0ifq+F2hc2QLdf/PMQDKyaDmCZ3vBHzKhgiAAd 16 | Q2s5CaiHMmwOSETml76Um/sCgYEAud+RLc96phzFgsGYOlk58od4GGnqPZO5JBgl 17 | M9xrHOG4VZifGdENm08OBWGZceDANnsI18gLM1IdhSi9PmkkBO+WVXf3/7PzxWUn 18 | s0bseAGM6+9zTP6aJ2DETa2WW99P70HYaiUl053kKRzYdyXTS6AtAIuznvhY3UEp 19 | wMfIthkCgYBn56NFJDuA0ZKm/azEHYoah7AaqTKT76Aa1wxlxy+hvoqGeWwBvhGD 20 | S+FsTjxociv3/E+yNc9CWjN+guIbUZntkmYOPCFjCJmX8dXz476O8VxWv/S+IP0h 21 | zt8g7+9c94gE27aoqXpyC7XRRLOtC0JJOzZaFOseQvUIbu/NtozrWQKBgCO0U2H2 22 | Yfv4uOQGJiTHMP9qkGI4LjvH3Z+WV8cfhx/UKCGhIKbH5pI33FyiQ+SBJMsSVT+F 23 | +MjR9EO48KlFbxrXnwwp8GSY/7GiXb7tV80xlw1XQNHAcoIv72Vwe9qICgXOozC4 24 | lAyTXtma5eX1SSJU0XAyZb2avQ87Tjbu6Zo5AoGAcg8kUUqtLydyg4sbqZqzvh4S 25 | DH6f9VEL3N7Jtn2E898i1T3G0Cls8V/46w//snLT9Az+AKqaQTi6nm6NLmCWY/3Z 26 | VZKkbuTtM3nyDZRSxt2I6Z5sdTp82gPs58jZeYLB5fwt5vLRQCItNckoVHicH2uC 27 | 4cu17ajUJ5Zk1QMOrpk= 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /src/main/java/com/xxg/network/netty/websocket/WebSocketServer.java: -------------------------------------------------------------------------------- 1 | package com.xxg.network.netty.websocket; 2 | 3 | import io.netty.bootstrap.ServerBootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioServerSocketChannel; 8 | import io.netty.handler.codec.http.HttpHeaders; 9 | import io.netty.handler.codec.http.HttpObjectAggregator; 10 | import io.netty.handler.codec.http.HttpServerCodec; 11 | import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; 12 | import io.netty.handler.codec.http.websocketx.WebSocketFrame; 13 | import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; 14 | import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; 15 | 16 | public class WebSocketServer { 17 | 18 | public static void main(String[] args) throws InterruptedException { 19 | EventLoopGroup bossGroup = new NioEventLoopGroup(); 20 | EventLoopGroup workerGroup = new NioEventLoopGroup(); 21 | try { 22 | ServerBootstrap b = new ServerBootstrap(); 23 | b.group(bossGroup, workerGroup) 24 | .channel(NioServerSocketChannel.class) 25 | .childHandler(new ChannelInitializer() { 26 | @Override 27 | public void initChannel(SocketChannel ch) throws Exception { 28 | ChannelPipeline pipeline = ch.pipeline(); 29 | pipeline.addLast(new HttpServerCodec()); 30 | pipeline.addLast(new HttpObjectAggregator(65536)); 31 | pipeline.addLast(new WebSocketServerCompressionHandler()); 32 | pipeline.addLast(new WebSocketServerProtocolHandler("/", null, true)); 33 | pipeline.addLast(new MyWebSocketServerHandler()); 34 | } 35 | }); 36 | ChannelFuture f = b.bind(8080).sync(); 37 | f.channel().closeFuture().sync(); 38 | } finally { 39 | workerGroup.shutdownGracefully(); 40 | bossGroup.shutdownGracefully(); 41 | } 42 | } 43 | } 44 | 45 | class MyWebSocketServerHandler extends SimpleChannelInboundHandler { 46 | 47 | @Override 48 | protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) { 49 | if (frame instanceof TextWebSocketFrame) { 50 | String request = ((TextWebSocketFrame) frame).text(); 51 | ctx.channel().writeAndFlush(new TextWebSocketFrame("收到: " + request)); 52 | } 53 | } 54 | 55 | @Override 56 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { 57 | 58 | // 握手成功后触发该事件 59 | if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) { 60 | WebSocketServerProtocolHandler.HandshakeComplete handshakeCompletedEvent = (WebSocketServerProtocolHandler.HandshakeComplete) evt; 61 | String uri = handshakeCompletedEvent.requestUri(); // 握手请求 URI 62 | HttpHeaders headers = handshakeCompletedEvent.requestHeaders(); // 握手请求头 63 | 64 | // TODO 这里可以获取握手请求 URL 中的参数,或对用户进行登录认证 65 | } 66 | } 67 | } --------------------------------------------------------------------------------