美文网首页
Socket 网络编程(二)

Socket 网络编程(二)

作者: zhzhgang | 来源:发表于2018-04-11 21:55 被阅读0次

Netty

Netty 实现通信的步骤:
1)创建两个 NIO 线程组,一个专门用于网络事件处理(接受客户端的连接),另一个则进行网络通信读写。
2)创建一个 ServerBootstrap 对象,配置 Netty 的一系列参数,例如接受传出数据的缓存大小等等。
3)创建一个实际处理数据的类 ChannelInitializer,进行初始化的准备工作,比如设置接受传出数据的字符集、格式、以及实际处理数据的接口。
4)绑定端口,执行同步阻塞方法等待服务器端启动即可。

示例代码:

Server.java

public class Server {

    public static void main(String[] args) throws Exception {
        //1 创建线两个程组 
        //一个是用于处理服务器端接收客户端连接的
        //一个是进行网络通信的(网络读写的)
        EventLoopGroup pGroup = new NioEventLoopGroup();
        EventLoopGroup cGroup = new NioEventLoopGroup();
        
        //2 创建辅助工具类,用于服务器通道的一系列配置
        ServerBootstrap b = new ServerBootstrap();
        b.group(pGroup, cGroup)     //绑定俩个线程组
        .channel(NioServerSocketChannel.class)      //指定NIO的模式
        .option(ChannelOption.SO_BACKLOG, 1024)     //设置tcp缓冲区
        .option(ChannelOption.SO_SNDBUF, 32*1024)   //设置发送缓冲大小
        .option(ChannelOption.SO_RCVBUF, 32*1024)   //这是接收缓冲大小
        .option(ChannelOption.SO_KEEPALIVE, true)   //保持连接
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                //3 在这里配置具体数据接收方法的处理
                sc.pipeline().addLast(new ServerHandler());
            }
        });
        
        //4 进行绑定 
        ChannelFuture cf1 = b.bind(8765).sync();
        //ChannelFuture cf2 = b.bind(8764).sync();
        //5 等待关闭
        cf1.channel().closeFuture().sync();
        //cf2.channel().closeFuture().sync();
        pGroup.shutdownGracefully();
        cGroup.shutdownGracefully();
    }
}

ServerHandler.java

public class ServerHandler extends ChannelHandlerAdapter {


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("server channel active... ");
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
            ByteBuf buf = (ByteBuf) msg;
            byte[] req = new byte[buf.readableBytes()];
            buf.readBytes(req);
            String body = new String(req, "utf-8");
            System.out.println("Server :" + body );
            String response = "进行返回给客户端的响应:" + body ;
            ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
            //.addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx)
            throws Exception {
        System.out.println("读完了");
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable t)
            throws Exception {
        ctx.close();
    }
}

Client.java

public class Client {

    public static void main(String[] args) throws Exception{
        
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap b = new Bootstrap();
        b.group(group)
        .channel(NioSocketChannel.class)
        .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel sc) throws Exception {
                sc.pipeline().addLast(new ClientHandler());
            }
        });
        
        ChannelFuture cf1 = b.connect("127.0.0.1", 8765).sync();
        //ChannelFuture cf2 = b.connect("127.0.0.1", 8764).sync();
        //发送消息
        Thread.sleep(1000);
        cf1.channel().writeAndFlush(Unpooled.copiedBuffer("777".getBytes()));
        cf1.channel().writeAndFlush(Unpooled.copiedBuffer("666".getBytes()));
        //cf2.channel().writeAndFlush(Unpooled.copiedBuffer("888".getBytes()));
        Thread.sleep(2000);
        cf1.channel().writeAndFlush(Unpooled.copiedBuffer("888".getBytes()));
        //cf2.channel().writeAndFlush(Unpooled.copiedBuffer("666".getBytes()));
        
        cf1.channel().closeFuture().sync();
        //cf2.channel().closeFuture().sync();
        group.shutdownGracefully();
        
        
        
    }
}

ClientHandler.java

public class ClientHandler extends ChannelHandlerAdapter{


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf buf = (ByteBuf) msg;
            
            byte[] req = new byte[buf.readableBytes()];
            buf.readBytes(req);
            
            String body = new String(req, "utf-8");
            System.out.println("Client :" + body );
            String response = "收到服务器端的返回信息:" + body;
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

    }

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

TCP 粘包、拆包问题

产生原因:

1)应用程序 write 写入的字节大小套接口发送缓冲区的大小。
2)进行 MSS 大小的 TCP 分段。
3)以太网帧的 payload 大于 MTU 进行 IP 分片。

解决方案:

1)消息定长,例如每个报文的大小固定为 200 个字节,如果不够,空位补空格。
2)在包尾部增加特殊字符进行分割,例如加回车等。
3)将消息分为消息头和消息体,在消息头中包含表示消息总长度的字段,然后进行业务逻辑的处理。

Netty 如何解决粘包、拆包问题:

1)分隔符类 DelimiterBasedFrameDecoder(自定义分隔符)
2)FixedLengthFrameDecoder(定长)

相关文章

  • 许世伟的Go语言基础 第五章总结

    第5章 网络编程 5.1 socket编程 以往socket编程: 建立socket:使用socket()函数。 ...

  • Day18总结

    一.网络通信过程TCP协议和UDP协议二.socket编程 1.socket编程定义:socket又叫套接字。指的...

  • 网络编程

    python学习笔记-网络编程 socket编程: socket()函数:socket.socket([famil...

  • 网络编程

    网络 Socket 基于TCP协议的Socket编程 基于UDP协议的Socket编程

  • python核心编程第三版

    第二章-网络编程 socket() 嵌套字创建tcp/ip套接字tcpsock - socket.socket(s...

  • 2018-09-12 day18-网络编程和http请求

    网络编程 socket 网络编程就是socket编程,socket就是套接字,就是进行数据通信的两端(服务器和客户...

  • Socket 网络编程(二)

    Netty Netty 实现通信的步骤:1)创建两个 NIO 线程组,一个专门用于网络事件处理(接受客户端的连接)...

  • socket网络编程(二)

    网络七层协议 网络七层协议由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。其中物理层、数...

  • 网络基础介绍

    网络编程的两种 TCP socket编程,是网络编程的主流。之所以叫Tcp socket编程,是因为底层是基于Tc...

  • Go语言的Socket编程

    我们在日常开发当中,几乎所有网络编程都是Socket编程,因为大部分底层网络的编程都离不开Socket编程。 什么...

网友评论

      本文标题:Socket 网络编程(二)

      本文链接:https://www.haomeiwen.com/subject/gkuyhftx.html