Socket究竟是干什么的?

从事业务开发太久,突然被问到Socket是什么这个问题?竟然一下子系统回答不上来,咳,可怕。

1.Socket是什么

了解Socket首先必须要对基础网络传输协议有一定的了解,比如OSI七层和TCP/IP五层标准网络架构有一定的了解。

TCP/IP五层:应用层,传输层,网络层,数据链路层,物理层;
OSI七层:应用层,表示层,会话层,传输层,网络层,数据链路层,物理层;
其中除了,表示层和会话层外,每一层都有自己的协议,也就是数据格式。
应用层 文件传输,电子邮件,文件服务,虚拟终端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet。
表示层 数据格式化,代码转换,数据加密 没有协议
会话层 解除或建立与别的接点的联系 没有协议
传输层 提供端对端的接口 TCP,UDP。
网络层 为数据包选择路由 IP,ICMP,RIP,OSPF,BGP,IGMP
数据链路层 传输有地址的帧以及错误检测功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
物理层 以二进制数据形式在物理媒体上传输数据 ISO2110,IEEE802,IEEE802.2。

这里给出一个问题,为什么一会七层,一会又五层,两者关系是啥?

上面只是网络传输架构,以及具体的协议格式,那么具体实现尼?
来了,Socket是对TCP/IP是对整个网络传输协议架构的封装,它的出现只是使得我们更加方便的使用TCP/IP协议栈而已。它提供了针对传输层TCP或者UDP编程的接口。

2.Socket例子

2.1 一个TCP连接
一个TCP连接由客户端Ip+端口号,服务端Ip+端口号确认!任何端不能创建一个相同的TCP连接!!否则,出错,Address already in use!

2.2 服务端-- 连接监听端
package socket;
 
import java.io.*;
import java.net.*;
 
public class TcpServer {
    public static void main(String[] args) throws Exception {
        //ServerSocket源码解析,指定了监听的端口号。
        ServerSocket server = new ServerSocket(9091);
        try {
            Socket client = server.accept();
            try {
                BufferedReader input =
                        new BufferedReader(new InputStreamReader(client.getInputStream()));
                boolean flag = true;
                int count = 1;
 
                while (flag) {
                    System.out.println("客户端要开始发骚了,这是第" + count + "次!");
                    count++;
                    
                    String line = input.readLine();
                    System.out.println("客户端说:" + line);
                    
                    if (line.equals("exit")) {
                        flag = false;
                        System.out.println("客户端不想玩了!");
                    } else {
                        System.out.println("客户端说: " + line);
                    }
 
                }
            } finally {
                client.close();
            }
            
        } finally {
            server.close();
        }
    }
}

从程序中可以看到,服务端使用ServerSocket监听一个端口号,客户端通过这个端口号和服务端建立连接。
当然,服务端默认使用本机ip,也可以指定一个IP(因为服务端可能存在多网卡,多ip)。


InetAddress bindip = InetAddress.getByName("192.168.1.168");
ServerSocket server = new ServerSocket(9091, 0, bindip);
2.3 客户端 – 连接发起端
package socket;
 
import java.io.*;
import java.net.*;
import java.util.Scanner;
 
public class TcpClient {
    public static void main(String[] args) throws Exception {
        Socket client = new Socket("127.0.0.1", 9091);
        try {
            PrintWriter output =
                    new PrintWriter(client.getOutputStream(), true);
            Scanner cin = new Scanner(System.in);
            String words;
 
            while (cin.hasNext()) {
                words = cin.nextLine();
 
                output.println(words);
 
                System.out.println("写出了数据: " + words);
            }
 
            cin.close();
        } finally {
            client.close();
        }
    }
}

但上面程序可以看到,客户端建立连接通信时候,需要指定服务端的IP和端口号。
但是客户端并未指定自己这端的端口号以及IP,注意,Socket客户端在和服务端连接时,会随机分配一个端口号以及使用本机IP。

3.Socket应用

Socket是一个最基本的一个TCP传输层协议的接口。
上面示例只是最简单一个Socket通信例子,要达到生产级别的应用,还远不止如此!

3.1 Dubbo中的应用

Dubbo是基于TCP协议的,底层的通信原理肯定也会使用Socket,只不过通过TCP协议传输的内容有自己格式规约(Dubbo自己的协议)。
当然,并不是指Dubbo改造TCP协议,而是Dubbo在TCP协议报文里传输的内容指定了一个固定格式。

一次Dubbo调用?
Consumer调用Provider的接口
1.通过注册中心Register随机找到一个Provider所在的机器IP+端口号。

IP+端口号是在Provider上报到Register注册中心的,上报的数据格式可能是Map,key是接口,value是当前机器的Ip+port。

2.按Dubbo协议组装传输的内容格式,其中包含了调用的具体接口名、方法名、参数序列化后的二进制内容。
3.通过Socket和Provider的机器建立连接,并传输Dubbo协议内容。
4.Provider监听本机上的对应IP+端口号,获取传入的内容。解析获得Provider调用的接口名、方法名、同样的序列化方式反序列化得到入参。
5.通过Java反射运行Provider上指定的方法,得到结果后,同样反序列化给Consumer端。
以上是远程调用的一个本质原理,其中涉及到序列化,反射,甚至要考虑多线程。Dubbo作为一个高可用,高扩展的RPC框架,其中内容远不止如此简单。

3.2 XxlJob上的应用
XxlJob是一个分布式任务调度平台。它包含了定时任务控制台、客户端。
控制台是对客户端具体定时任务的调度。
客户端是对具体定时任务的执行。

这里就不说具体怎么使用了。只问一个问题,客户端是在其他机器上部署的,控制台是怎样找到客户端并执行具体定时任务的?
客户端简单实现

@Slf4j
@Component
@JobHandler(value = "subscribeTagTask")
public class SubscribeSelectTask extends IJobHandler {

    private final AManager aManager;
    private final SManager sManager;

    @Override
    public ReturnT<String> execute(String s) throws Exception {
        return ReturnT.SUCCESS;
    }

    public SubscribeSelectTask(AManager aManager,
                               SManager sManager) {
        this.aManager = aManager;
        this.sManager = sManager;
    }
}

这里简单说下:
1.客户端启动的时候,会对配有JobHandler注解的定时任务进行扫描,并上报当前定时任务运行的机器的IP+Port到控制台。
同时对该IP+Port进行监听,等待控制台调度消息。
2.控制台将上报内容存储到已经配好的这个任务。
3.控制台在达到调度时间的进行调度时候,会从多个客户端里面随机或者轮询(可配置)选择一个客户端IP+Port,建立TCP连接。
并传输调度指令。
4.客户端监听到这个消息后,解析控制台发的调度指令,找到对应的定时任务,怎么找到尼,或许是按照JobHandler配置的Value
通过反射找到指定的定时任务,并通过反射执行。
TIPS:上面XXLJOB的客户端其实也是Socket对应的服务端,会进行Socket连接监听。
以上就是大致的原理,具体细节要深入源码,如有不对,敬请指正。

参考文章
https://blog.youkuaiyun.com/github_34606293/article/details/78230456
https://blog.youkuaiyun.com/wzy_1988/article/details/17131381

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值