网络编程(一)

一:socket

操作系统提供的网络编程的API,就称为"socket api"
socket,就认为是"网络编程API" 的统称
操作系统提供的socket api ,不止一套,而是有好几套
1:流式套接字:给TCP使用的
2:数据报套接字:给UDP使用的.
3:Unix域套接字:不能跨主机通信,只是本地主机上的进程与进程之间的通信方式(用的很少).

二:TCP vs UDP

TCP和UDP都是传输层协议,都是给应用层提供服务的.
TCP特点:有连接,可靠传输,面向字节流,全双工.
UDP特点:无连接,不可靠传输,面向数据报,全双工.

2.1:有连接 vs 无连接

有连接就好比打电话,得电话先打通了,然后才能说话
(1)可以选择,接听,也可以选择直接挂掉.
(2)要建立连接的双方,各自保存对方的信息.
无连接就好比,发短信/发微信,不需要先接通,直接上来就发
(1)无法拒绝
(2)通信双方不需要保存到对方的信息.

2.2:可靠传输 vs 不可靠传输

可靠传输:
(1)可靠!=安全
安全:指的是,你要传输的数据,是否容易被黑客截获,一旦截获后,是否会造成严重的影响
(2)要传输的数据,是尽可能的传输给对方,而不是确保100%
在 网络通信的过程中,可能会存在很多的意外情况,比如丢包:A给B传输10个数据报,B实际上只收到了9个.
为什么会出现丢包??
因为网络环境,太复杂了,A传输给B,中间可能会经历很多的交换机和路由器,而这些交换机和路由器也不只是转发我自己的数据,要转发很多数据.比如:某个交换机/路由器,非常繁忙,繁忙到,要处理的数据量,已经超过了自身的硬件水平限制,此时,多出来的数据,就无法转发,会被直接丢弃掉.
而且,丢包是随机的过程,你无法预知什么时候会出现丢包,也无法预知,哪个路由器/交换机会出现丢包.
为了对抗丢包,就引入"可靠传输",TCP就具备可靠传输的特点,内部就提供了一系列的机制,来实现可靠传输.
不可靠传输:
UDP则是不可靠传输,传输数据的时候,根本不关心对方是否收到.
但可靠传输是有代价的,最典型的就是:传输数据的时候,效率会大打折扣.
UDP比TCP的传输快

2.3:面向字节流 vs 面向数据报

面向字节流:
TCP和文件操作,具有相同的特点.
面向数据报:
传输数据的基本单位,是一个一个的UDP数据报,一次读写,只能读写一个完整的UDP数据报,不能读写半个,也不能读写一个,

网络传输的基本单位:
1:数据报:datagram =>UDP
2:数据段:Segment =>TCP
3:数据包 :Packet =>IP
4:数据帧:Frame =>数据链路层

2.4:全双工 vs 半双工

全双工:
一条链路,能够进行双向通信:既可以读(接收),也可以写(发送)
半双工:
一条链路,只能进行单向通信,要么是接收,要么是发送,不能同时进行.

二级目录

三:UDP

UDP的 socket API 重点是 两个类.
1:DatagramSocket
系统中,本身就有socket 这样的概念,系统中的socket ,可以理解成一种socket文件,通过对socket文件的读写操作,就相当于针对网卡这个硬件设备进行读写.
其实,可以直接对网卡进行操作,只不过比较复杂,通过socket文件的读写操作(句柄),进而对网卡进行读写操作就变得简单了.
类比:我们想要操作空调,可以直接踩个凳子,去空调上面按,也可以拿着遥控器进行操作,
具有"遥控器属性"这样的概念,在计算机中称为"句柄(handle)"
对普通文件的操作,就是针对硬盘设备的抽象,直接操作硬盘,能操作,不方便,借助文件这个概念(遥控器),就可以很快的完成了.
DatagramSocket:可以认为是"操作网卡"的遥控器,针对这个对象进行读写操作,就是针对网卡进行读写操作.
2:DatagramPacket:
针对UDP数据报的一个抽象表示.
一个DatagramPacket对象,就相当于一个UDP数据报,一次发送/一次接收,就是传输了一个DatagramPacket对象.

### Redis 分布式锁Redisson 的实现原理 #### 1. **Redis 分布式锁** Redis 分布式锁的核心思想是通过 `SETNX` 和 `EXPIRE` 来实现加操作。在早期版本(Redis 2.6.12之前),由于 `SETNX` 不支持设置过期时间,因此需要分两步完成:先调用 `SETNX` 创建键值对表示定状态,再调用 `EXPIRE` 设置过期时间以防止死[^3]。 然而这种两步操作无法保证原子性,可能会因网络延迟或其他异常导致未成功创建却设置了过期时间。为此,Redis 2.6.12引入了新的命令 `SET key value NX PX milliseconds`,其中 `NX` 表示只有当键不存在时才执行设置操作,`PX` 则用于指定毫秒级的过期时间。这种方式能够在一个命令内完成加并设定超时,从而有效解决了上述问题。 #### 2. **Redisson 实现分布式锁** Redisson 是基于 Redis 开发的一个 Java 客户端库,它不仅实现了更高级别的抽象接口,还提供了多种类型的分布式对象和服务功能。对于分布式锁而言,Redisson 提供了一种更加健壮可靠的解决方案——`RLock` 接口及其子类实例化方式。 - **加逻辑** Redisson 使用 Lua 脚本来确保整个加过程具有原子性。该脚本会检查目标资源是否已被占用;如果未被占用,则尝试获取并将当前线程 ID 记录下来作为持有者的唯一标识符[^1]。 - **续命机制** 当某个客户端成功获得之后,Redisson 会在后台启动一个定时器任务定期向服务器发送续约请求延长的有效期限,直到显式解为止。此设计可以避免因长时间运行的任务而导致提前失效的情况发生[^2]。 - **自旋重试策略** 如果初次未能取得所需资源,则按照预定义间隔不断重复尝试直至达到最大等待时限或最终放弃争夺控制权。 - **公平性和可靠性保障措施** 在某些特殊情况下(比如网络分区), 可能会出现部分节点认为自己已经拿到了全局唯一的,但实际上其他地方也有竞争者存在的情形下, redisson 还特别考虑到了这一点并通过内部复杂的协调算法尽可能减少冲突概率[^4]. #### 性能对比分析 | 特性 | Redis 原生分布 | Redisson | |-------------------------|------------------------------------------|----------------------------------| | 加效率 | 较高 | 略低 | | 安全性 | 存在网络抖动等问题 | 更安全可靠 | | 功能扩展能力 | 单纯提供基础加解鎖功能 | 支持更多特性如自动续租、可重入等 | | 易用程度 | 需要开发者手动处理很多细节 | API 封装良好易于集成 | 从表中可以看出虽然原生态方法简单高效但在实际应用过程中往往面临诸多挑战;而借助第三方工具包则可以在一定程度上弥补这些不足之处. ```java // 示例代码展示如何利用Redisson进行分布式锁管理 import org.redisson.api.RLock; import org.redisson.api.RedissonClient; public class DistributedLockExample { private final RedissonClient redissonClient; public void acquireAndReleaseLock(String lockName) throws InterruptedException{ RLock lock = redissonClient.getLock(lockName); try { boolean isLocked = lock.tryLock(10, TimeUnit.SECONDS); // 尝试获取最长等待时间为10秒 if(isLocked){ System.out.println(Thread.currentThread().getName()+" acquired the lock."); Thread.sleep(5000L); // Simulate some work }else{ System.err.println("Failed to get lock after waiting..."); } } finally { if(lock.isHeldByCurrentThread()){ lock.unlock(); System.out.println(Thread.currentThread().getName()+ " released the lock."); } } } } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十一.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值