JDK中socket源码解析
目录
1、Java.net包
1. Socket通信相关类
2. URL和URI处理类
3. 网络地址和主机名解析类
4. 代理和认证相关类
5. 网络缓存和Cookie管理类
6. 其他网络相关工具类
2、什么是socket?
3、JDK中socket核心Api
4、核心源码
1、核心方法
2、本地方法
3、linux是怎么处理链接的?
5、demo验证
建立连接
发送数据
断开连接
1、Java.net包
java.net包提供了一组用于网络编程的类,支持开发网络应用程序和处理网络通信。java.net包可以大致分为六个部分:
1. Socket通信相关类
这些类用于实现基于 TCP 和 UDP 协议的网络通信。
- Socket:实现客户端的 TCP 套接字,允许程序与远程主机建立连接并传输数据。
- ServerSocket:实现服务器的 TCP 套接字,用于监听客户端连接并接受连接请求。
- DatagramSocket:用于 UDP 套接字通信,通过不可靠的无连接数据报协议传输数据。
- MulticastSocket:扩展了 DatagramSocket,用于支持多播组通信,允许数据发送到多个接收者。
- SocketAddress:表示一个套接字地址,通常用于绑定到特定 IP 地址和端口。
- InetSocketAddress:表示 IP 地址和端口的组合,继承自SocketAddress 。
2. URL和URI处理类
这些类用于处理统一资源定位符(URL)和统一资源标识符(URI)。
- URL:表示一个 URL(统一资源定位符),用于定位网络资源。支持从指定的 URL 中读取和解析数据。
- URI:表示一个 URI(统一资源标识符),提供对 URI 的结构化处理。
- URLStreamHandler:处理 URL 的协议细节,通常用于为不同协议(如 http、ftp)定义特定的处理逻辑。
- URLConnection:表示到 URL 所引用的资源的通信链接,可以处理资源的获取和发送。
- HttpURLConnection:继承自URLConnection ,用于处理 HTTP 协议的 URL 连接,支持 HTTP 请求和响应。
- JarURLConnection:继承自URLConnection ,用于从 JAR 文件中获取资源。
3. 网络地址和主机名解析类
这些类用于表示 IP 地址和解析主机名。
- InetAddress:表示 IP 地址,可以通过主机名或 IP 地址来查找和操作网络主机。
- Inet4Address:表示 IPv4 地址。
- Inet6Address:表示 IPv6 地址。
- NetworkInterface:表示网络接口(如以太网接口),用于获取和操作本地计算机的网络接口。
4. 代理和认证相关类
这些类用于处理网络代理和认证功能。
- Proxy:表示网络通信中的代理设置,支持 HTTP 和 SOCKS 等代理类型。
- ProxySelector:用于选择代理服务器的策略,可以根据 URI 的类型来选择合适的代理。
- Authenticator:用于实现网络请求中的认证机制,允许为 HTTP 和 FTP 请求提供用户名和密码等凭据。
- PasswordAuthentication:表示用户名和密码对,用于 Authenticator 类中的认证操作。
5. 网络缓存和Cookie管理类
这些类用于处理缓存和 Cookie 的存储和管理。
- CookieHandler:用于管理 HTTP 协议中的 Cookie。
- CookieManager:具体的 Cookie 管理器实现,允许存储和检索 Cookie。
- CacheRequest:表示缓存系统中的请求,允许将资源写入缓存。
- CacheResponse:表示缓存系统中的响应,允许从缓存中读取资源。
6. 其他网络相关工具类
一些提供额外网络功能的工具类。
- DatagramPacket:用于表示数据报,包含通过 DatagramSocket 发送或接收的数据。
- IDN:提供对国际化域名的处理,允许将 Unicode 域名转换为符合 Punycode 编码的 ASCII 字符串。
- NetworkInterface:表示计算机上的网络接口,允许列举和操作网络接口。
- StandardProtocolFamily:定义标准协议族(如 INET 和INET6),用于套接字通信。
2、什么是socket?
一个IP地址和一个端口号称为一个套接字(socket)。此术语出现在最早的TCP规范(RFC793, Page 5)中。我们知道进程通信的方法有管道、命名管道、信号、消息队列、共享内存、信号量,这些方法都要求通信的两个进程位于同一个主机。但是如果通信双方不在同一个主机又该如何进行通信呢?在计算机网络中有一个tcp/ip协议族,使用tcp/ip协议族就能达到我们想要的效果,如下图所示:

socket就是提供了tcp/ip协议的抽象,对外提供了一套接口,同过这个接口就可以统一、方便的使用tcp/ip协议的功能了,使得我们可以在在不同的计算机或网络设备之间建立连接,允许数据的发送和接收。
3、JDK中socket核心Api
| 方法签名 | 作用 | |
| 构造函数 | public ServerSocket() | 创建未绑定的服务器套接字。稍后需要手动调用 bind() 来绑定到特定的端口。 |
| public ServerSocket(int port) | 创建绑定到指定端口的服务器套接字,默认使用所有可用的网络接口(IP 地址)。 | |
| public ServerSocket(int port, int backlog) | 创建绑定到指定端口的服务器套接字,并指定连接请求队列的最大长度 backlog。 | |
| public ServerSocket(int port, int backlog, InetAddress bindAddr) | 创建绑定到指定 IP 地址和端口的服务器套接字,指定 backlog 来定义连接请求的队列长度。 | |
| public Socket(String host, int port)(客户端) | 创建一个客户端 Socket 并连接到指定的远程主机 host 和端口 port。 | |
| 绑定端口方法 | public void bind(SocketAddress endpoint)(客户端、服务端) | 将服务器套接字绑定到指定的 SocketAddress,通常是 InetSocketAddress,以监听特定端口。 |
| public void bind(SocketAddress endpoint, int backlog) | 绑定到指定的 SocketAddress 并设置连接请求队列的最大长度 backlog,队列满时拒绝新连接请求。 | |
| 监听客户端 | protected void listen(int backlog) | 将服务器套接字置于监听状态,backlog 参数指定允许等待连接的最大队列长度,超过该长度的连接请求将被拒绝。 |
| 接受客户端请求 | public Socket accept() throws IOException | 等待客户端的连接请求,接受成功后返回一个与客户端通信的新 Socket 对象。 |
| 尝试连接服务端socket | public void connect(SocketAddress endpoint, int timeout)(客户端) | 尝试连接到远程服务器指定的 SocketAddress 地址,timeout 参数指定连接超时时间(毫秒)。如果在超时时间内未能连接,则抛出异常。 |
| 数据输入输出 | InputStream getInputStream() | 获取 Socket 的字节输入流 |
| OutputStream getOutputStream() | 获取 Socket 的字节输出流 | |
| InetAddress getInetAddress() | 获取对端的 IP 地址 | |
| InetAddress getPort() | 获取对端的端口号 | |
4、核心源码
1、核心方法
客户端和服务端最重要的两个类是Socket和Server Socket,这俩一个代表tcp通信的客户端,一个代表服务端。从源码来看,ServerSocket和socket内部分别持有一个SocketImpl对象,用于将对应的方法代理给native方法。以服务端ServerSocket为例:
构造函数中通过调用setImpl()创建了一个SocketImpl实现类,所有的创建链接、读写数据系统交互的本地方法都是在实现类中调用,也就是将对应的方法代理给native方法。
public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {setImpl();if (port < 0 || port > 0xFFFF)throw new IllegalArgumentException("Port value out of range: " + port);if (backlog < 1)backlog = 50;try {bind(new InetSocketAddress(bindAddr, port), backlog);} catch(SecurityException e) {close();throw e;} catch(IOException e) {close();throw e;}} |
setImpl();方法在JDK17与JDK8中的实现方式不一样。JDK13之前使用的是PlainSocketImpl这个实现类(阻塞式 I/O),JDK 13后,Socket 的连接过程通过 NioSocketImpl 实现,采用了 NIO(非阻塞 I/O)技术来实现高效的网络连接和数据传输。具体可以参考:JDK13新特性
private void setImpl() {SocketImplFactory factory = ServerSocket.factory;if (factory != null) {impl = factory.createSocketImpl();} else {impl = SocketImpl.createPlatformSocketImpl(true);}}static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) { (默认传参false)if (USE_PLAINSOCKETIMPL) {return (S) new PlainSocketImpl(server);} else {return (S) new NioSocketImpl(server);}} |
创建对应的socket实现类以后,调用bind方法绑定端口与开启监听,真正的本地方法的调用都在:getImpl().bind(epoint.getAddress(), epoint.getPort())、getImpl().listen(backlog)中实现:
public void bind(SocketAddress endpoint, int backlog) throws IOException {if (backlog < 1)backlog = 50;try {@SuppressWarnings("removal")SecurityManager security = System.getSecurityManager();if (security != null)security.checkListen(epoint.getPort());getImpl().bind(epoint.getAddress(), epoint.getPort());getImpl().listen(backlog);bound = true;} catch(SecurityException e) {bound = false;throw e;} catch(IOException e) {bound = false;throw e;}} |
static void bind(ProtocolFamily family, FileDescriptor fd,InetAddress addr, int port) throws IOException{boolean preferIPv6 = isIPv6Available() &&(family != StandardProtocolFamily.INET);if (addr.isLinkLocalAddress()) {addr = IPAddressUtil.toScopedAddress(addr);}bind0(fd, preferIPv6, exclusiveBind, addr, port);} |
2、本地方法
JDK8源码中的路径:C:\jdk-8\src\solaris\native\java\net\PlainSocketImpl.cJNIEXPORT void JNICALL
Java_java_net_PlainSocketImpl_socketBind(JNIEnv *env, jobject this,jobject iaObj, jint localport) {} |
3、linux是怎么处理链接的?
前面提到的核心Api中,有关建立socket连接的Api中都有一个参数叫做backlog,源码中这个参数如果不设置,系统默认值为50,那么这个参数到底是什么?
public ServerSocket(int port) throws IOException {this(port, 50, null);}public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException {setImpl();} |
关于这个参数,只需要看懂下面这张图就明白了:


Linux内核协议栈为TCP连接管理使用两个队列,一个是SYN队列(半链接队列,用来保存处于SYN_SENT和SYN_RECV状态的请求),一个是accpetd队列(用来保存处于established状态,但是应用层没有调用accept取走的请求),这两个队列是内核实现的,当服务器绑定、监听了某个端口后,这个端口的SYN队列和ACCEPT队列就建立好了。如图,整个过程就是:
1. 当SYN包到达了服务器后,内核会把这一信息放到SYN队列(即未完成握手队列)中,同时回一个SYN+ACK包给客户端。
2. 一段时间后,客户端再次发来了针对服务器SYN包的ACK网络分组时,内核会把连接从SYN队列中取出,再把这个连接放到ACCEPT队列(即已完成握手队列)中。
3. 服务器在第3步调用accept时,其实就是直接从ACCEPT队列中取出已经建立成功的连接套接字而已。
那么问题来了,当这两个队列满了后,新的请求到达了又将发生什么?
- 对于SYN队列,若队列满,则会直接丢弃请求,即新的SYN网络分组会被丢弃,这个问题好解决,客户端接收不到回复,会再一次发送,然后服务端继续丢弃,知道队列有空闲的位置。而客户端如果一直接收不到回复,发几次之后就会停止。
- 对于ACCEPT队列的处理就有点复杂了,分两种情况:
-
- 如果server端设置了sysctl_tcp_abort_on_overflow,那么server会发送rst给client,并删除掉这个链接。默认情况下是不会设置的。
- 如果没有设置sysctl_tcp_abort_on_overflow ,server端只是标记连接请求块的acked标志,并且连接建立定时器,会遍历半连接表,重新发送synack,重复上面的过程,如果重传次数超过synack重传的阀值,会把该连接从半连接链表中直接删除。
5、demo验证
建立连接
- 1、服务端创建服务端套接字,并开启客户端监听与等待连接请求
- 2、客户端客户端套接字,尝试连接服务端
- 3、客户端调用private static native int connect0(boolean preferIPv6,
FileDescriptor fd,
InetAddress remote,
int remotePort) - 3次握手建立连接

发送数据
- 1、客户端调用OutputStreamWriter发送数据
- 2、服务端调用InputStreamReader接收数据

断开连接
- 手动使客户端关闭连接
- 4次挥手断开连接

相关文章:
JDK中socket源码解析
目录 1、Java.net包 1. Socket通信相关类 2. URL和URI处理类 3. 网络地址和主机名解析类 4. 代理和认证相关类 5. 网络缓存和Cookie管理类 6. 其他网络相关工具类 2、什么是socket? 3、JDK中socket核心Api 4、核心源码 1、核心方法 2、本地方法 3、lin…...
Ansible自动化运维项目实战指南
Ansible自动化运维项目实战指南 在当今快速发展的IT环境中,运维工作的复杂性和规模性日益增加,传统的手动运维方式已难以满足高效、可靠、可重复性的需求。Ansible作为一款开源的自动化运维工具,凭借其简单易用、无需代理、基于SSH的架构特性…...
MySQL【知识改变命运】10
联合查询 0.前言1.联合查询在MySQL里面的原理2.练习一个完整的联合查询2.1.构造练习案例数据2.2 案例:⼀个完整的联合查询的过程2.2.1. 确定参与查询的表,学⽣表和班级表2.2.2. 确定连接条件,student表中的class_id与class表中id列的值相等2.…...
Java学习教程,从入门到精通, Java 基础语法(4)
1、Java 基础语法 一、Java 简介与开发环境搭建 Java 简介:Java 是一种面向对象的编程语言,具有跨平台、安全、稳定等特点。Java 主要应用于企业级应用、Android 应用开发、大数据处理等领域。开发环境搭建:搭建 Java 开发环境需要安装 JDK…...
反编译工具-Jclasslib的使用,与Java方法调用的探索
这里写目录标题 前言IDEA下查看字节码的两种方法使用idea自带的插件工具安装插件 为什么没有看出方法调用关系原因分析工厂举例 知识补充语言java可移植性 总结 前言 画时序图的时候,我想验证下方法的调用是否写的正确。方法调用不仅涉及到程序的基本逻辑流程&#…...
力扣 简单 876.快慢指针
文章目录 题目介绍题解 题目介绍 题解 class Solution {public ListNode middleNode(ListNode head) {ListNode slow head, fast head;while(fast ! null && fast.next ! null){slow slow.next;fast fast.next.next;}return slow;} }...
FineReport 计算同比增长
1、数据库查询 SELECTt1.年,t1.月,t1.总金额 AS 同期金额,t1.仓库名称,t2.总金额 AS 上期金额 FROMtest t1LEFT JOIN test t2 ON ( t1.年 t2.年 1 ) AND t1.月 t2.月 AND t1.仓库名称 t2.仓库名称2、配置字段 月份字段加后缀 月 数据列加后缀 计算同比增长率 if(LEN(B3)0 …...
从0开始深度学习(12)——多层感知机的逐步实现
依然以Fashion-MNIST图像分类数据集为例,手动实现多层感知机和激活函数的编写,大部分代码均在从0开始深度学习(9)——softmax回归的逐步实现中实现过 1 读取数据 import torch from torchvision import transforms import torchv…...
如何利用OpenCV和yolo实现人脸检测
在之前的blog里面,我们有介绍OpenCV和yolo的区别,本文就人脸检测为例,分别介绍下OpenCV和yolo的实现方式。 OpenCV实现人脸检测 一、安装 OpenCV 首先确保你已经安装了 OpenCV 库。可以通过以下方式安装: 使用包管理工具安装&…...
015集——c# 实现CAD excel交互(CAD—C#二次开发入门)
第一步:添加引用 程序集—>扩展 namespace WindowsFormsApp2 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){}private void 获取当前excel_Click(object sender, EventArgs e…...
【计网笔记】以太网
经典以太网 总线拓扑 物理层 Manchester编码 数据链路层 MAC子层 MAC帧 DIX格式与IEEE802.3格式 IEEE802.3格式兼容DIX格式 前导码(帧开始定界符SOF) 8字节 前7字节均为0xAA第8字节为0xAB前7字节的Manchester编码将产生稳定方波,用于…...
Java 入门基础篇14 - java面向对象思想以及特性
学习目标: 一、目标 面向对象思想类和对象对象的创建和使用属性和方法封装 开始学习: 二、编程思想 2.1 什么是编程思想 做人有做人的原则,编程也有编程的原则。这些编程的原则,就叫做编程思想。 2.2 面向过程和面向对象 二…...
第15篇:网络架构优化与综合案例分析
目录 引言 15.1 网络性能优化的方法与工具 15.1.1 带宽管理与流量控制 15.1.2 负载均衡 15.1.3 缓存优化 15.2 网络故障的排查与解决 15.2.1 常用的网络故障排查工具 15.2.2 网络故障排查案例 15.3 网络安全架构的综合设计案例 15.3.1 企业网络安全架构的要求 15.3.…...
UI自动化测试实战
补充:Selenium主要用于Web页面的自动化测试,它可以模拟用户的各种操作,如点击、输入、滚动等,来测试网页的功能。而Appium是一个开源的移动端自动化测试工具。 一、自动化测试实战章节 自动化测试流程测试用例编写项目自动化测试…...
东方智者颜廷利:以哲学思想促进世界和谐与无私奉献
【本社讯】在全球化的今天,东方智慧与哲学思想正逐渐成为促进世界和谐与理解的重要力量。近日,祖籍齐鲁大地山东济南的东方智者颜廷利以其深邃的哲学思想和对人类社会的深刻洞察,引起了国际社会的广泛关注。 颜廷利,一位致力于哲学研究与实践的智者,他的思想跨越古今,融合了东…...
基于 springboot vue停车场管理系统 设计与实现
博主介绍:专注于Java(springboot ssm 等开发框架) vue .net php phython node.js uniapp 微信小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设,从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不…...
如何验证ssl私钥和证书是否匹配?
从证书(CRT)文件提取公钥 openssl x509 -in server.crt -pubkey -noout | openssl sha256从证书签名请求(CSR)文件提取公钥 openssl req -in server.csr -pubkey -noout | openssl sha256从私钥(KEY)文件…...
MongoDB的基本操作
🌷数据库准备 🎈Mongoshell 1.在指定目录下创建mongodb文件夹、其子文件log和data以及mongodb.log cd /home/ubuntu mkdir -p mongodb/data mkdir -p mongodb/log touch mongodb/log/mongodb.log 执行mongodb命令启动mongdb服务 mongod --dbpath /h…...
spring mvc后端实现过程
文章目录 一、Spring mvc1、controller1.1、LoginController011.2、LoginController 2、service2.1、LoginService2.1、LoginInimplements 3、dao3.1、LoginMapper3.1、LoginMapper.xml 4、实体类 一、Spring mvc 1、controller 控制器层、处理用户的请求和响应, …...
102005
import os os.environ["CUDA_VISIBLE_DEVICES"] "0" # 设定使用的 GPUimport tensorflow as tf from dataset import generate_data import numpy as np from model import enhancednet# 检查 TensorFlow 是否可以识别 GPU gpus tf.config.list_physica…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
