博客主页

手把手使用Java实现一个Socks5代理

1. 前言

上一篇文章介绍了socks5协议的工作过程和协议的细节,通过上一篇文章我们可以认识到socks5协议主要有3个阶段,分别为: 协商、请求,Relay。本文将手把手使用Java语言实现一个简单的socks5代理

特别提醒: 本文目的仅作为加深socks5协议理解,其中的代码并不是严谨的代码,也没考虑其他的情况。在实际的开发过程中,需要考虑更多的意外情况。

上一篇文章中有一张时序图展示了socks5的大概工作过程,本文将使用Java把这些过程一一实现。

~replace~/assets/images/socks5/client-socks5_f.jpg

Read more

理解socks5协议的工作过程和协议细节

1. 前言

本位将由浅入深带大家详细了解socks5协议。文章首先会对socks协议进行简单介绍,接着会介绍socks5协议的使用场景,然后介绍它的工作工程,最后介绍协议的细节(握手、数据转发)。

2. 协议介绍

2.1 什么是socks协议

啥是socks协议呢? 这里贴一段维基百科对它的定义

SOCKS is an Internet protocol that exchanges network packets between a client and server through a proxy server

大概的意思是: socks是一种互联网协议,它通过一个代理服务器在客户端和服务端之间交换网络数据。简单来说,它就是一种代理协议,扮演一个中间人的角色,在客户端和目标主机之间转发数据。

~replace~/assets/images/socks5/socks5_01.jpeg

socks协议位于OSI模型中的第五层,即会话层(Session Layer)。

Read more

理解Java中的Bridge Method

bridge method又叫synthetic method,它是由Java编译器自动生成的一个合成方法,这个方法不会出现在源码中,也不能显式调用。我们先通过一个例子对bridge method有一个感性的认识。

// Code 1-1
class Animal {
  public Animal getAnimal() {
    return new Animal();
  }
}

class Dog extends Animal {
  public Dog getAnimal() {
    return new Dog();
  }
}

上面定义了Animal和Dog两个类,Dog是Animal的subclass,且Dog类override了Animal的getAnimal方法。如果你现在尝试去编译Dog,很大概率是可以直接通过编译,不过当我们尝试使用JDK 1.4以下版本编译,就是另外一回事了。

javac org/wiyi/bridge/Dog.java
org/wiyi/bridge/Dog.java:6: getAnimal() in org.wiyi.bridge.Dog cannot override g
etAnimal() in org.wiyi.bridge.Animal; attempting to use incompatible return type

found   : org.wiyi.bridge.Dog
required: org.wiyi.bridge.Animal
  public Dog getAnimal() {
             ^
1 error

Read more

深入理解面向对象中的多态

多态

多态并非是计算机科学领域的专有名词,在其他领域比如生物领域也有使用。比如猫科动物中,有狮子、老虎、豹、山猫等,其中雄性狮子会有很长的胡须等,都是现实生活中的多态。

基于上面的描述,我们不难理解计算机领域中的”多态”,实际上它也是对现实世界的一种抽象。在现实中,猫可以代指小猫咪、老虎、狮子等动物,具体到计算机领域的抽象,可以用下面语法表达:

Cat cat = new Tiger();

用一个符号来表现同一种类型的不同形态,这就是多态。相信所有Java程序员对上面语法早已烂熟于心,这种语法属于多态中的一个分支,叫Subtyping(也叫subtype polymorphism,子类型多态)。

多态是类型系统中一个重要的概念,在Java语言中,实现了3种类型的多态,分别为:

  • Ad hoc polymorphism (特殊的多态)
  • subtype polymorphism (子类型多态)
  • Parametric polymorphism (参数化多态)

本文将详细介绍这3种类型的多态,进一步加深对多态的理解。

Read more

理解Mysql InnoDB引擎中的锁

Mysql是支持ACID特性的数据库。我们都知道”C”代表Consistent,当不同事务操作同一行记录时,为了保证一致性,需要对记录加锁。在Mysql中,不同的引擎下的锁行为也会不同,本文将重点介绍Mysql InnoDB引擎中常见的锁。

准备

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `age` tinyint(4) DEFAULT '0',
  `phone` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

#插入基础数据
INSERT INTO `user` (`id`, `name`, `age`, `phone`)
VALUES
	(1, '张三', 18, '13800138000'),
	(2, '李四', 20, '13800138001'),
	(3, '王五', 22, '13800138002'),
	(4, '赵六', 26, '13800138003'),
	(5, '孙七', 30, '13800138004');

为了方便讲解,创建一张user表,设置age的字段为普通索引,并填充以下数据。本文所有的sql语句均基于这张表。

id name age Phone
1 张三 18 13800138000
2 李四 20 13800138001
3 王五 22 13800138002
4 赵六 26 13800138003
5 孙七 30 13800138004

Read more

带你彻底理解Linux五种I/O模型

在编程中I/O是必不可少的操作。日常中,我们最常接触的就是Blocking I/O,也就是常说的阻塞I/O。相信你也听过同步非阻塞I/O(Non-Blocking I/O),异步I/O(Asynchronous I/O)。

要理解这些I/O模型并不是一件容易的事,相信你也在网上看到许多人尝试对这些概念解释,不过我认为目前并没有什么文章能对它们解释的比较清晰的文章。尤其是很多一知半解的人胡乱举例,更是加深理解难度。

知识准备

阅读本文之前,希望读者具备以下的知识,否则看了也是一脸懵。

  • 了解你所知语言中的基本I/O操作
  • User space & Kernel space 的概念
  • 理解File Descriptor。如果不懂,请移步理解linux中的file descriptor(文件描述符)。建议读者不管对file descriptor有没有了解,都去阅读这篇文章,对你理解I/O模型会有非常大的帮助。

看完了上面的内容,希望读者已经理解了下面内容

  1. 程序无法直接访问硬件资源,对磁盘(硬件)的读写需要发起system call,让kernel处理。
  2. 大部分和I/O有关的system call,都需要把fd(file descriptor)作为参数传递给kernel。

Read more

理解linux中的file descriptor(文件描述符)

file descriptor(以下简称fd)又叫文件描述符,他是一个抽象的指示符,用一个整数表示(非负整数)。它指向了由系统内核维护的一个file table中的某个条目(entry)。这个解释可能过于抽象,不过在正式详细介绍fd之前,有必要先了解用户程序和系统内核之间的工作过程。

注: 本文描述的所有场景仅限于类unix系统环境,在windows中这玩意叫file handle(臭名昭著的翻译: 句柄)。

User space & Kernel space

现代操作系统会把内存划分为2个区域,分别为Use space(用户空间) 和 Kernel space(内核空间)。用户的程序在User space执行,系统内核在Kernel space中执行。

用户的程序没有权限直接访问硬件资源,但系统内核可以。比如读写本地文件需要访问磁盘,创建socket需要网卡等。因此用户程序想要读写文件,必须要向内核发起读写请求,这个过程叫system call。

内核收到用户程序system call时,负责访问硬件,并把结果返回给程序。

FileInputStream fis = new FileInputStream("/tmp/test.txt");
byte[] buf = new byte[256];
fis.read(buf);

上面代码的流程如下图所示

/assets/images/fd/us_ks.png

Read more

深入浅出Redis Sentinel

Sentinel是Redis官方提供的高可用方案,传统的master slave(现在叫repliacation)模式中,当master故障时,需要手动修改配置文件指定新的master,Sentinel解决了这个问题,可以不需人工干预自动切换新的master。

sentinel节点是一个独立的进程,它不仅监测master节点,同时也会监测slave、sentinel节点的状态。

Sentinel介绍

架构

       +----+
       | M1 |
       | S1 |
       +----+
          |
+----+    |    +----+
| R2 |----+----| R3 |
| S2 |         | S3 |
+----+         +----+

Configuration: quorum = 2

Read more