• Socket说明


    概念

    socket

    socket 通信是基于TCP/IP 网络层上的一种传送方式,我们通常把TCP和UDP称为传输层。

    socket,又称套接字,是在不同的进程间进行网络通讯的一种协议、约定或者说是规范

    socket编程,它更多的时候像是基于TCP/UDP等协议做的一层封装或者说抽象,是一套系统所提供的用于进行网络通信相关编程的接口

    七层模型

    在这里插入图片描述

    socket属于应用层,socket的应用层协议是HTTP协议

    socket 代表的是其中的5、6层,也就是会话层、表示层

    1. 会话层负责 建立客户端和服务端(一般称主动发起连接的一方为客户端,另一方为服务端)的连接
    2. 表示层负责数据格式的转化、加密解密等操作

    socket是基于应用服务与TCP/IP通信之间的一个抽象,他将TCP/IP协议里面复杂的通信逻辑进行分装,对用户来说,只要通过一组简单的API就可以实现网络的连接

    TPC/IP协议是传输层协议,主要解决数据 如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据

    我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如 果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET等,也 可以自己定义应用层协议。WEB使用HTTP协议作应用层协议,以封装HTTP文本信息,然后使用TCP/IP做传输层协议将它发到网络上

    socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议

    socket编程基本流程

    在这里插入图片描述

    API

    服务端使用ServerSocket绑定IP和端口,
    使用Accept监听端口是否有客户端发送连接请求,一旦有客户端发送连接请求,服务端就回送连接信息,正式建立连接。

    Server端和Client端都可以通过Send,Write等方法与对方通信。

    创建服务端socket

    
    // 初始化服务端socket并且绑定9999端口
    ServerSocket serverSocket  =new ServerSocket(9999);
    
    • 1
    • 2
    • 3
    // 创建服务端socket 绑定端口
    ServerSocket serverSocket = new ServerSocket();
    //绑定ip
    serverSocket = new ServerSocket(8088, 10, InetAddress.getByName("192.168.0.110"));
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    创建客户端连接

    // 和服务器创建连接
    Socket socket = new Socket("192.168.0.111", 8088);
    
    
    • 1
    • 2
    • 3

    服务器端的基本实现

    public class TcpSocketServer {
    
      public static void main(String[] args) {
            try {
                // 创建服务端socket 绑定端口
                ServerSocket serverSocket = new ServerSocket();
                //绑定ip
                serverSocket = new ServerSocket(8088, 10, InetAddress.getByName("192.168.0.110"));
                // 创建客户端socket 用户下面接收客户端socket对象
                Socket socket = new Socket();
                System.out.println("等待客户端连接...");
                //循环监听等待客户端的连接
                while(true){
                    // 监听客户端  没有接受到数据才会停在此处 接受到往下执行
                    socket = serverSocket.accept();
                   //发送内容实现线程的创建
                    ServerThread thread = new ServerThread(socket);  
                    thread.start();
                    //获取客户端的ip
                    InetAddress address=socket.getInetAddress();
                    System.out.println("当前链接的客户端的IP:"+address.getHostAddress());
                }
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
    	}
        
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    线程方法:

    public class ServerThread extends Thread{
    
        private Socket socket = null;
    
        public ServerThread(Socket socket) {
    
            this.socket = socket;
        }
        public void run() {
            InputStream is=null;
            InputStreamReader isr=null;
            BufferedReader br=null;
            OutputStream os=null;
            PrintWriter pw=null;
            try {
                is = socket.getInputStream();
                isr = new InputStreamReader(is);
                br = new BufferedReader(isr);
                String info = null;
                while((info=br.readLine())!=null){
                    System.out.println("客户端:"+info);
                }
                //非关闭连接 仅关闭一方的发送状况
                socket.shutdownInput();
                os = socket.getOutputStream();
                pw = new PrintWriter(os);
                pw.write("服务器欢迎你1");
                pw.flush();
            } catch (Exception e) {
                // TODO: handle exception
            } finally{
                //关闭资源
                try {
                    if(pw!=null)
                        pw.close();
                    if(os!=null)
                        os.close();
                    if(br!=null)
                        br.close();
                    if(isr!=null)
                        isr.close();
                    if(is!=null)
                        is.close();
                    if(socket!=null)
                        socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    客户端的基本实现

    public class TcpSocketClient {
        public static void client() throws InterruptedException {
            try {
                // 和服务器创建连接
                Socket socket = new Socket("192.168.0.111", 8088);
                // 要发送给服务器的信息
                OutputStream os = socket.getOutputStream();
                PrintWriter pw = new PrintWriter(os);
                pw.write("状态已改变");
                //flush方法是用于将输出流缓冲的数据全部写到目的地。
                //所以一定要在关闭close之前进行flush处理,即使PrintWriter有自动的flush清空功能
                pw.flush();
                socket.shutdownOutput();
                // 从服务器接收的信息
                InputStream is = socket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String info = null;
                while ((info = br.readLine()) != null) {
                    System.out.println("我是客户端,服务器返回信息:" + info);
                }
                br.close();
                is.close();
                os.close();
                pw.close();
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    可以去看这篇博客这篇博客,参考socket的实现

    socket长连接

    通常情况下,如果说到了socket长连接,他们一般特指TCP/IP连接协议,这个协议是面向连接的可靠的数据流服务,它可以维持长时间,持续的交换数据包。

    因而我们所说的长连接便是基于这个协议实现的,同时socket又为我们实现了这个功能,因此,这个 连接协议的长时间维持,也被称为socket长连接

    也可以这样理解:指在一个连接上可以连续发送多个数据包,在连接保持期间,如果没有数据包发送,需要双方发链路检测包整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接

    socket短连接

    与长连接是长时间维持住连接以方便持续发送数据,但是很多时候我们并不需要长时间发送,我们只需要确认我们发送了,服务器处理了,就可以了。

    所以,短连接就产生了,它是TCP/IP连接协议的使用完即关闭

    短连接:连接服务是每次请求都建立链接,交互完之后关闭链接

    我们的http协议便是基于此而来

    长连接和短连接

    在实际应用中,长连接他并不是真正意义上的长连接,他们是通过一种称之为心跳包或者叫做链路检测包,去定时检查socket 是否关闭,输入/输出流是否关闭

    socket本身并不是一直通信协议,而是一套接口的封装。

    而TCP/IP协议组里面的应用层包括FTP、HTTP、TELNET、SMTP、DNS等协议,

    我们知道,http1.0是短连接,http1.1是长连接

    在打开http通信协议里面在Response headers中可以看到这么一句Connection:keep-alive,就是表示长连接,但是他并不是一直保持的连接,他有一个时间段

    如果想一直保持这个连接怎么办?

    在制定的时间内让客户端和服务端进行一个请求,请求可以是服务端发起,也可以是客户端发起,通常我们是在客户端不定时的发送一个字节数据给服务端,这个就是我们称之为心跳包,想想心跳是为了检测人活着,心会定时的跳动,就是这个原理。

  • 相关阅读:
    hdfs常用命令行
    flink故障恢复的流程(从检查点恢复状态)
    shiro反序列化漏洞复现(CVE-2016-4437)
    小迈科技可能的面试问题
    11 C++设计模式之享元(Flyweight)模式
    Linux CentOS 8(HTTPS的配置与管理)
    如何解决分布式Session共享的问题
    13基于PCA的人脸识别,程序已调通,可将自己的数据替换进行识别,得到识别准确率结果,MATLAB平台。
    管理多租户环境之PDB快照
    腾讯云服务器如何使用WooCommerce 应用镜像搭建电商独立网站
  • 原文地址:https://blog.csdn.net/yyuggjggg/article/details/126223455