Java网络编程:socket与Netty

  • Java网络编程:socket与Netty
    • TCP/IP介绍
      • 简介
      • 数据传输
      • TCP粘包和黏包
        • 现象
        • 为什么出现
        • 如何解决
    • Socket介绍
      • 介绍
      • 功能开发
    • Netty介绍
      • 简介
      • 部分重点类和方法
        • ServerBootstrap
        • option / handler / attr方法
        • Bootstrap
        • Channel
        • EventLoop
        • ChannelFuture
        • ChannelHandler
        • ChannelPipeline
        • LengthFieldBasedFrameDecoder
          • LengthFieldBasedFrameDecoder参数

Java网络编程:socket与Netty

  • 说到Java 网络编程,第一印象肯定是Netty。由于Java IO编程偏底层、不易用,Netty应运而生。Netty 并没有 Java 核心类库那些强烈的通用性、跨平台等各种负担,针对性能等特定目标以及 Linux 等特定环境,采取了一些极致的优化手段。
  • 说道网络通信,也避免不了TCP/IP协议和socket技术,下面分别讲一下,错误或不准确的地方,欢迎指正。

TCP/IP介绍

简介

  • TCP/IP传输协议,即传输控制/网络协议,也叫作网络通讯协议。它是在网络的使用中的最基本的通信协议。
  • TCP/IP传输协议对互联网中各部分进行通信的标准和方法进行了规定。并且,TCP/IP传输协议是保证网络数据信息及时、完整传输的两个重要的协议。
  • TCP/IP传输协议是严格来说是一个四层的体系结构,应用层、传输层、网络层和数据链路层都包含其中。

数据传输

  • 在网络编程中,TCP/IP统一采用big endian方式传送数据
  • 现行的计算机都是以八位一个字节为存储单位
  • little endian把低位存放到高位,而big endian把低位存放到低位.
  • 现在主流的CPU,intel系列的是采用的little endian的格式存放数据,而motorola系列的CPU采用的是big endian。

TCP粘包和黏包

现象

  • TCP粘包是指发送方发送的若干个数据包到接收方时粘成一个包。从接收缓冲区来看,后一个包数据的头紧接着前一个数据的尾
  • 当TCP连接建立后,Client发送多个报文给Server,TCP协议保证数据可靠性,但无法保证Client发了n个包,服务端也按照n个包接收。Client端发送n个数据包,Server端可能收到n-1或n+1个包

为什么出现

  • 发送方原因: TCP默认会使用Nagle算法。而Nagle算法主要做两件事:1)只有上一个分组得到确认,才会发送下一个分组;2)收集多个小分组,在一个确认到来时一起发送。所以,正是Nagle算法造成了发送方有可能造成粘包现象
  • 接收方原因: TCP接收方采用缓存方式读取数据包,一次性读取多个缓存中的数据包。自然出现前一个数据包的尾和后一个收据包的头粘到一起。

如何解决

  1. 添加特殊符号,接收方通过这个特殊符号将接收到的数据包拆分开 - DelimiterBasedFrameDecoder特殊分隔符解码器
  2. 每次发送固定长度的数据包 - FixedLengthFrameDecoder定长编码器
  3. 在消息头中定义长度字段,来标识消息的总长度 - LengthFieldBasedFrameDecoder自定义长度解码器

Socket介绍

介绍

  • socket不属于某种协议,只是网络编程技术,任何编程语言都支持socket技术开发,目的就是解决两个应用程序通讯的问题
  • Socket实现了TCP/IP,TCP/IP只是一份文档,各个不同的语言根据自己的需求对这个协议进行不同的解析,而在JAVA里对TCP/IP的解析实现就是Socket。

功能开发

  1. Socket 实现了TCP/IP协议,可以连接到网络上的终端,并收发数据

  2. ServerSocket 用于服务端,可以监听服务端口,等待客户端连接,连接后可以生成用于传输数据的Socket

  3. 创建服务端

ServerSocket serverSocket = new ServerSocket(9999);Socket socket =  serverSocket.accept();  //等待客户端连接
  1. 创建客户端
Socket socket = new Socket("100.100.28.26", 9999);// 注意:注册网络权限;不能在主线程做网络连接
  1. 客户端发送消息
DataOutputStream writer = new DataOutputStream(socket.getOutputStream());writer.writeUTF("嘿嘿,你好啊,服务器..");  // 写一个UTF-8的信息
  1. 服务端接收消息
DataInputStream reader = new DataInputStream( socket.getInputStream());String msg = reader.readUTF();
  • 也可以使用Netty很方便的实现socket编程

Netty介绍

简介

  • 按照官方定义,它是一个异步的、基于事件 Client/Server 的网络框架,目标是提供一种简单、快速构建网络应用的方式,同时保证高吞吐量、低延时、高可靠性。
  • Netty 的设计强调了 “Separation Of Concerns”,通过精巧设计的事件机制,将业务逻辑和无关技术逻辑进行隔离,并通过各种方便的抽象,一定程度上填补了了基础平台和业务开发之间的鸿沟,更有利于在应用开发中普及业界的最佳实践。
  • 从网络协议的角度,Netty 除了支持传输层的 UDP、TCP、SCTP协议,也支持 HTTP(s)、WebSocket 等多种应用层协议,它并不是单一协议的 API
  • 在应用中,需要将数据从 Java 对象转换成为各种应用协议的数据格式,或者进行反向的转换,Netty 为此提供了一系列扩展的编解码框架,与应用开发场景无缝衔接,并且性能良好。

部分重点类和方法

ServerBootstrap

  • 服务器端程序的入口,这是 Netty 为简化网络程序配置和关闭等生命周期管理,所引入的 Bootstrapping 机制。
  • 我们通常要做的创建 Channel、绑定端口、注册 Handler 等,都可以通过这个统一的入口,以Fluent API 等形式完成,相对简化了 API 使用

option / handler / attr方法

  • 都定义在AbstractBootstrap中, 所以服务端和客户端的引导类方法调用都是调用的父类的对应方法。
  • 赋值方法使用时,option / handler / attr 方法主要是针对boss线程组,childHandler / childOption / childAttr主要是针对worker线程组
  • option: 设置通道的选项参数, 对于服务端而言就是ServerSocketChannel, 客户端而言就是SocketChannel;
  • handler: 设置主通道的处理器, 对于服务端而言就是ServerSocketChannel,也就是用来处理Acceptor的操作;对于客户端的SocketChannel,主要是用来处理 业务操作;
  • attr: 设置通道的属性;
  • 对于服务端而言,有两种通道需要处理, 一种是ServerSocketChannel:用于处理用户连接的accept操作, 另一种是SocketChannel,表示对应客户端连接。
  • 以child开头的方法,都定义在ServerBootstrap中,表示处理或配置服务端接收到的对应客户端连接的SocketChannel通道。

Bootstrap

  • Bootstrap则是 Client 端的通常入口。
  • 对于客户端,一般都只有一种channel,也就是SocketChannel。

Channel

Channel,作为一个基于 NIO 的扩展框架,Channel 和 Selector 等概念仍然是 Netty 的基础组件,但是针对应用开发具体需求,提供了相对易用的抽象。

EventLoop

这是 Netty 处理事件的核心机制。我们可以使用 EventLoopGroup。我们在 NIO 中通常要做的几件事情,如注册感兴趣的事件、调度相应的 Handler 等,都是 EventLoop 负责。

ChannelFuture

这是 Netty 实现异步 IO 的基础之一,保证了同一个 Channel 操作的调用顺序。Netty 扩展了 Java 标准的 Future,提供了针对自己场景的特有Future定义。

ChannelHandler

这是应用开发者放置业务逻辑的主要地方,也是我上面提到的“Separation Of Concerns”原则的体现。

ChannelPipeline

它是 ChannelHandler 链条的容器,每个 Channel 在创建后,自动被分配一个 ChannelPipeline。在使用时,我们可以通过 ServerBootstrap 注册 ChannelInitializer,并且实现 initChannel 方法,而在该方法中则承担了向 ChannelPipleline 安装其他 Handler 的任务。

LengthFieldBasedFrameDecoder

  • 基于长度字段的帧解码器,自定义长度解决TCP粘包黏包问题
  • Netty从TCP缓冲区中读取字节, 把这些字节交给LengthFieldBasedFrameDecoder进行解码
  • 解码的操作是根据设定的规则, 根据规则,从字节中解码出来有意义的数据, 然后把数据再交给后续的Handler处理.
  • LengthFieldBasedFrameDecoder本质上是ChannelHandler,一个处理入站事件的ChannelHandler
  • LengthFieldBasedFrameDecoder需要加入ChannelPipeline中,且位于链的头部
  • 公式: 发送数据包长度 = 长度域的值 + lengthFieldOffset + lengthFieldLength + lengthAdjustment
LengthFieldBasedFrameDecoder参数
  • maxFrameLength - 发送的数据帧最大长度
  • lengthFieldOffset - 定义长度域位于发送的字节数组中的下标。换句话说:发送的字节数组中下标为${lengthFieldOffset}的地方是长度域的开始地方
  • lengthFieldLength - 用于描述定义的长度域的长度。换句话说:发送字节数组bytes时, 字节数组bytes[lengthFieldOffset, lengthFieldOffset+lengthFieldLength]域对应于的定义长度域部分
  • lengthAdjustment - 满足公式: 发送的字节数组bytes.length - lengthFieldLength = bytes[lengthFieldOffset, lengthFieldOffset+lengthFieldLength] + lengthFieldOffset + lengthAdjustment
  • initialBytesToStrip - 接收到的发送数据包,去除前initialBytesToStrip位
  • failFast - true: 读取到长度域超过maxFrameLength,就抛出一个 TooLongFrameException。false: 只有真正读取完长度域的值表示的字节之后,才会抛出 TooLongFrameException,默认情况下设置为true,建议不要修改,否则可能会造成内存溢出

Java网络编程:socket与Netty相关推荐

  1. Java网络编程 Socket、ServerSocket 详解,方法介绍及完整代码示例

    Java网络编程 Socket.ServerSocket 详解,方法介绍及完整代码示例 概念 什么是网络编程? 网络编程是指编写运行在多个设备(计算机)的程序,这些设备通过网络连接起来.当这些通过网络 ...

  2. java网络编程socket\server\TCP笔记(转)

    java网络编程socket\server\TCP笔记(转) 2012-12-14 08:30:04|  分类: Socket |  标签:java  |举报|字号 订阅 1 TCP的开销 a  连接 ...

  3. Java网络编程——Socket 编程

    Socket 编程 Socket编程是在TCP/IP上的网络编程,但是Socket在上述模型的什么位置呢.这个位置被一个天才的理论家或者是抽象的计算机大神提出并且安排出来 我们可以发现Socket就在 ...

  4. JAVA网络编程Socket常见问题 【长连接专题】

    一. 网络程序运行过程中的常见异常及处理 第1个异常是 java.net.BindException:Address already in use: JVM_Bind. 该异常发生在服务器端进行new ...

  5. Java网络编程socket基础学习

    文章目录 InetAddress类 URL类 URLConnection类 使用URLConnection发送post请求 Socket类 DatagramSocket MulticastSocket ...

  6. 【Java网络编程】:Netty实现OIO和NIO

    承接上文:https://blog.csdn.net/hxcaifly/article/details/85274664 前言 单纯地使用Java JDK来实现网络NIO是一件开发成本非常高的事情.然 ...

  7. java网络编程Socket实现客户端向服务端发送信息

    (可按目录按需阅读,我一般会整理的比较细) 前置知识 java IO Socket 什么是socket?socket字面意思其实就是一个插口或者套接字,包含了源ip地址.源端口.目的ip地址和源端口. ...

  8. JAVA 网络编程 Socket 详细说明,实现客户端和服务端相互推送消息

    客户端代码: package com.lcx.socket;import java.io.BufferedReader; import java.io.BufferedWriter; import j ...

  9. java网络编程Socket中SO_LINGER选项的用法解读

    http://blog.sina.com.cn/s/blog_6b1990eb0101171o.html 1:设置该选项: public void setSoLinger(boolean on, in ...

  10. Java网络编程——Socket

    文章目录 服务器端(单线程) 服务器端(多线程) 客户端 服务器端(单线程) public class MySocketServer1 {private int port;private Server ...

最新文章

  1. python pip
  2. 创建型设计模式对比总结 设计模式(八)
  3. 25.计算机和计算器的区别
  4. 从JVM指令层面看try-catch-finally返回值问题
  5. ios UITableView顶部向下偏移
  6. simulink将值传递给mask封装下的模块
  7. lua 获取网络时间_Lua脚本引擎教程:学习路线
  8. MySQL划重点-查询-聚合
  9. mybatis自动生成service、dao、mapper
  10. 8086汇编语言程序设计
  11. 打车软件系统分析与设计方案
  12. 巨详细一文教你如何撰写商业计划书
  13. Hello December
  14. Pandas数据分析教程(2)-数据读取之普通索引、loc/iloc索引
  15. 【Linux系列文章】系统管理
  16. 通俗理解 机器学习中的偏差和方差
  17. 不要使用容易被误解的名字
  18. java.lang.RuntimeException: A TaskDescription‘s primary color should be opaque
  19. 被误解的tinyint(1)
  20. 做了6年的Java,mysql去重查询方法

热门文章

  1. 递归 算法 编程技巧
  2. 数据库服务器搭建系统,服务器系统搭建SQL数据库
  3. 有时候努力,并不是自己心甘情愿
  4. pb对Web Service的操作可使用两种方式实现
  5. 编写函数,接收一个字符串,分别统计大写字母、小写字母、数字、其他字符的个数,并以元组的形式返回结果。
  6. Apache Solr7.4 入门教程
  7. 网络安全如何学习?(学习路线及资料)
  8. Python自动化网络运维
  9. 赵青-《剑侠情缘网络版》开发回顾
  10. 解决警告: Failed to scan JAR[...] java.util.zip.ZipException: error in opening zip file