[Java] I/O底层原理之二:网络IO及网络编程
首先我们来看一下当访问一个域名时它的过程
- 查找 DNS
- 首先,浏览器检查缓存中有没有
- 浏览器缓存中没有,则查找操作系统中有没有配置这个对应关系
- 如果操作系统中也没有,则去 DNS 查找,即发送DNS报文:传输层(UDP数据报)-> 网络层(IP数据包)-> 数据链路层(协议单元)
- 如果发送时 ARP 缓存中没有相关数据,则发送 ARP 广播,等待 ARP 回应
- ARP 回应后,将 IP 地址与下一跳 MAC 地址写入 ARP 缓存表
- 经过多次转发后,数据到达 DNS 服务器,并解析到 IP 地址
我们先来看一下 TCP/IP 分层与 OSI 分层的关系
网络层 —— IP(网络之间的互联网协议)、ARP(地址解析协议)、RARP、ICMP
传输层 —— TCP(传输控制协议)、UDP(用户数据报协议)
应用层 —— TeInet(远程登录服务的标准协议)、SMTP(电子邮件协议)、NFS(网络文件服务协议)、SNMP(网络管理协议)、FTP(文本传输协议)、HTTP(超文本传输协议)
本篇博客主要讲述 TCP 协议和 UDP 协议在 Java 中的应用,下面我们来看一下两者的区别:
- TCP 协议是一种链接可靠的传输协议,通过 TCP 协议传输,得到的是一个顺序无差错的数据流。但是可靠的传输是要付出代价的,对数据的验证会占用计算机处理时间和网络带宽。所以 TCP 传输效率不如 UDP 高。
- UDP 协议是一种无链接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传送至目的地,但达到目的地的时间及内容的正确性都是不能保证的。在不需要严格保证传输可靠性时,可以使用 UDP 协议,如视频、音频等。
一、Socket与ServerSocket
1 TCP协议
TCP连接的状态转换图如下
注:SYN 表示建立链接、FIN 表示关闭链接、ACK 表示响应、PSH 表示有数据传输、RST 表示链接重置。
- CLOSED:初始状态,在超时或连接关闭时也会进入此状态。
- LISTEN:服务端在等待连接时的状态。
- SYN-SENT:客户端发起连接并发送 SYN 给服务端后等待的状态。如果不能连接,则进入 CLOSED 状态。
- SYN-RCVD:服务端接受客户端的 SYN 请求,由 LISTEN 状态进入此状态。同时回应一个 SYN、ACK 给客户端。
- ESTABLISHED:数据传输状态,服务端和客户端建立连接后的状态。
- FIN-WAIT-1:主动关闭的一方进入此状态。等待远程TCP连接中断请求,或先前的连接中断请求的确认
- FIN-WAIT-2:主动关闭的一方接收另一方的 FIN ACK进入的状态。
- CLOSE-WAIT:被动关闭的一方收到 FIN 后进入的状态,接收到 FIN 的同时发送 ACK。
- LAST-ACK:被动关闭的一方发起关闭请求。
- CLOSING:
- TIME-WAIT:
1 建立连接的步骤(三次握手)
- 客户端发送 SYN 给服务端
- 服务端回应 ACK 和 SYN 给客户端
- 客户端发送 ACK 给服务端
2 断开链接的步骤(四次挥手)
- 客户端发送 FIN 给服务端
- 服务端回应 ACK
- 服务端关闭链接,发送 FIN 给客户端
- 客户端回应 ACK 给服务端
2 Socket
一个 Socket 实例代表了一个通信链路,当连接建立成功后,服务器和客户端都会各拥有一个 Socket 实例,且这两个实例都会拥有一个 InputStream 和 OutputStream,以此来传输数据。在 InputStream 和 OutputStream 中会各有一个缓存区,数据写入和读取都是通过这个缓存区完成的。通过 OutputStream 将数据写入到其 SendQ 队列中,当队列填满时,数据将被传递到 InputStream 的 RecvQ 队列中,如果这时 RecvQ 已满,则 OutputStream 的 write() 方法将会阻塞,直到 RecvQ 队列有足够空间容纳 SendQ 发送的数据。要注意的是,缓存区的大小及读写宿舍非常影响连接的传输效率,而且由于是阻塞式,如果两遍同时传递数据有可能发生死锁。
[Java] I/O底层原理之二:网络IO及网络编程的更多相关文章
- 深入源码分析SpringMVC底层原理(二)
原文链接:深入源码分析SpringMVC底层原理(二) 文章目录 深入分析SpringMVC请求处理过程 1. DispatcherServlet处理请求 1.1 寻找Handler 1.2 没有找到 ...
- java面试-CAS底层原理
一.CAS是什么? 比较并交换,它是一条CPU并发原语. CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B.当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什 ...
- 【Spring Data JPA篇】JPA的底层原理(二)
一.接口继承结构 二.底层原理
- [Java] I/O底层原理之一:字符流、字节流及其源码分析
关于 I/O 的类可以分为四种: 关于字节的操作:InputStream 和 OutPutStream: 关于字符的操作:Writer 和 Reader: 关于磁盘的操作:File: 关于网络的操作: ...
- 基于JAVA Socket的底层原理分析及工具实现
前言 在工作开始之前,我们先来了解一下Socket 所谓Socket,又被称作套接字,它是一个抽象层,简单来说就是存在于不同平台(os)的公共接口.学过网络的同学可以把它理解为基于传输TCP/IP协议 ...
- Java 注解及其底层原理
目录 什么是注解? 注解的分类 Java自带的标准注解 元注解 @Retention @Documented @Target @Inherited @Repeatable 自定义注解 自定义注解的读取 ...
- (转载)Java NIO:NIO原理分析(二)
NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如果我们使用 ...
- [Java] I/O底层原理之三:NIO
本篇文章参考自并发编程网 一.NIO 的概述 NIO 由以下几个核心组成 Channels Buffers Selectors 选择器用于监听多个通道的事件(如:链接打开.数据达到),单个线程可以监听 ...
- Java 总结 数据底层原理 【包括 ArrayList、LinkedList、hash table、HashMap、Hashtable、ConcurrentHashMap、hash code、HashSet、LinkedHashMap、LinkedHashSet】
1.ArrayList (1)底层是由动态数组实现的[使用了List接口]. (2)动态数组是长度不固定,随着数据的增多而变长. (3)如果不指定,默认长度为10,当添加的元素超过当前数组的长度时,会 ...
随机推荐
- stl源码剖析 详细学习笔记 算法(4)
//---------------------------15/03/31---------------------------- //lower_bound(要求有序) template<cl ...
- Js_字体滚动换颜色
<html><head><meta http-equiv="Content-Type" content="text/html; charse ...
- python代码实现经典排序算法
排序算法在程序中有至关重要的作用, 不同算法的时间复杂度和空间复杂度都有所区别, 这影响着程序运行的效率和资源占用的情况, 经常对一些算法多加练习, 强化吸收, 可以提高对算法的理解, 进而运用到实践 ...
- 浅谈我的UI设计之路
时光匆匆,进入UI学习已经快两个月了,这段时间过得很充实,因为有压力才有收获. 还记的刚刚学习手绘的时候,对于这个行业只有一个初步的认识,知道自己喜欢,但是真正学习的时候才发现,我要学习的东西还有很多 ...
- B1010.一元多项式求导
12/25 #include<bits/stdc++.h> using namespace std; void solve(){ int A,B,coef,exp; cin>> ...
- A. Elections
链接 [http://codeforces.com/contest/1043/problem/A] 题意 有n个投票人已经投个对手ai票,让你求最小的k使得k-ai加起来大于,对手得票总和 分析 一个 ...
- 第二阶段团队冲刺——One
个人任务: 司宇航:处理第一次启动服务器500的问题. 季方:优化cookie第一次运行出错的问题. 王金萱:修改注册界面. 马佳慧:修改登录界面. 站立会议: 任务看板和燃尽图:
- 【助教】浅析log4j的使用
有不少童鞋私信我一些在写代码时候遇到的问题,但是无法定位问题出在哪里,也没有日志记录,实际上,写日志是开发项目过程中很重要的一个环节,很多问题都可以从日志中找到根源,从而定位到出错位置,为解决问题提供 ...
- css3-文本新增属性
rgba:a是设透明度值 应用:background:rgb(255,255,255,0.5) color:rgb(255,255,255,0.5) border:1px solid rgb(255, ...
- 链表的C/C++实现
一个链表实现,函数声明放在 list.h 头文件汇总,函数定义放在list.cpp 中,main.cpp 用来测试各个函数. 1.文件list.h // list.h #ifndef __LIST_H ...