zoukankan      html  css  js  c++  java
  • http协议下:为什么请求与响应会做到准确误的对应。不会出现请求与响应的错乱

    互联网通信是套接字进行通信的,套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
    非常非常简单的举例说明下:套接字=Ip address+ TCP/UDP + port。

    java 针对TCP 和 UDP进行了分别的开发封装: Socket,DatagramSocket (早期 JAVA开发者没有开发,DatagramSocket,TCP和UDP都是使用socket的进行开发的,后期加上了DatagramSocket后就把socket中开发UDP的API 废弃了,
    现在我们通常说socket开发tcp,DatagramSocket开发UDP)我们通常使用的互联网开发都是tcp,http 建立在tcp之上的协议,即:一个请求一个响应,请求与响应
    本质都是socket。也就是说socket与socket之间的通信,通信完毕就会结束链接,即无状态的链接,即这次连接和下次连接都是独立的交互。
    请求与响应是一一对应的,不会出现A的响应给了B的请求,因为socket通信是靠四元组进行对接通信的
    socket: 四元组 本地IP,本地Port,目标IP,目标Port

    serversocket:本质也是socket,为了开发服务器这一角色,所以将socket封装成了serversocket,创建serversocket的时候底层会创建一个socket,然后
    会绑定这个socket,同时监听这个socket的端口号并且会提前创建一个用于响应的socket。这样就会做到其他的socket请求该serversocket中的socket,那么监听器就会监听到并触发创建一个新的socket与请求socket进行通信,并且重新监听(扩展:如果还没有来的及从新监听,就在这时,突然有大量的请求过来,那么此时服务器很有可能会崩溃也有你可能拒绝你的请求,此时就出现了消息中间件,比如kafka,activeMQ 等即,让请求消息先来我这里排队,拍好队形在一个一个的去请求,这样就不会突然出现高并发了,放在服务器受不了,最后一个简单的案例说明。 )。并且会提前创建一个socket,等待请求。
    源码:
      public Socket accept() throws IOException {
            if (isClosed())
                throw new SocketException("Socket is closed");
            if (!isBound())
                throw new SocketException("Socket is not bound yet");
            Socket s = new Socket((SocketImpl) null); //提前创建好socket 响应
            implAccept(s);  //当没有请求时线程会停在这里,等待请求 
            return s;
        }


    当客户端创建请求socket时,Socket socket = new Socket("localhost",6472); 当请求socket链接到服务器时,socket才算创建成功,否者创建socket失败并会
    报错:Exception in thread "main" java.net.ConnectException: Connection refused: connect
    当请求socket创建成功后: 四元组 本地IP,本地Port,目标IP,目标Port 都会初始化完成,
                                    本地IP(假设为172.168.17.9),本地Port(java底层会随机给一个未占用的port,假设为2635)
                                    目标IP(服务器的IP,假设为192.168.17.88),目标Port(服务器的端口 假设为 8080) 

    此时accept()收到请求并且针对当前请求的socket返回一个响应socket,并且该响应socket的四元组 本地IP,本地Port,目标IP,目标Port
     都会初始化完成,                                                                                     
                                    本地IP(服务器当前的IP:192.168.17.88),本地Port(java底层会随机给一个未占用的port,假设为1526),
                                    目标IP(请求的IP:172.168.17.9)目标Port(请求的端口:2635 ) 
                                    
    此时,请求与响应才会做到了准备无误的对应。才不会出现请求与响应的错乱。

    demo:

    package com.jvm.others.socket_;
    import java.net.Socket;
    public class Demo2Soket { //客户端
        public static void main(String[] args) throws Exception {
            
            Socket socket = new Socket("localhost",6478);
            String hostAddress = socket.getLocalAddress().getHostAddress();
            int localPort = socket.getLocalPort();
            SocketUtiles.pringHostAndPort(socket);
            
        }
    }
    客户端打印结果:
         Local socket Host : 127.0.0.1
         Local socket HostAddress : 127.0.0.1
         Local socket Port : 60737
         des socket Host : localhost
         des socket HostAddress : 127.0.0.1
         des socket Port : 6478
         当前请求时间 15 5944


    package com.jvm.others.socket_;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
    public class Demo2ServerSocket { //服务器
          public static void main(String[] args) throws Exception {
            ServerSocket ss = new ServerSocket(6478);
            while(true){
            Socket accept = ss.accept();
            SocketUtiles.pringHostAndPort(accept);
            }
             }
    }

    服务器打印方式:
           Local socket Host : 127.0.0.1
           Local socket HostAddress : 127.0.0.1
           Local socket Port : 6478
           des socket Host : 127.0.0.1
           des socket HostAddress : 127.0.0.1
           des socket Port : 60737
           当前请求时间 15 5944
           

    扩展代码       
    并发案例服务器受不了拒绝了你:

    package com.jvm.others.socket_;
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    //模拟客户端请求
    public class DemoSocket {
        public static void main(String[] args) throws Exception {
            for(int i = 0;i<1000;i++){
            Socket socket = new Socket("localhost",6466);
            String hostAddress = socket.getLocalAddress().getHostAddress();
            int localPort = socket.getLocalPort();
            SocketUtiles.pringHostAndPort(socket);
            }
        }
    }

    package com.jvm.others.socket_;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
    //模拟服务器
    public class DemoSocketServer {
        static int i= 1;
      public static void main(String[] args) throws Exception {
        ServerSocket ss = new ServerSocket(6466);
        while(true){
        Socket accept = ss.accept();
        if(i==1){
            Date date = new Date();
            System.out.println("开始睡觉 当前时间为 : "+date.getHours()+" "+date.getMinutes()+" "+date.getSeconds());
           Thread.sleep(4000); //模拟来不及监听,停了4秒
           Date date2 = new Date();
            System.out.println("睡觉结束 当前时间为 : "+date2.getHours()+" "+date2.getMinutes()+" "+date.getSeconds());
        }
        i++;
        SocketUtiles.pringHostAndPort(accept);
        }
         }
    }
            
    //工具类  
    package com.jvm.others.socket_;
    import java.net.Socket;
    import java.util.Date;
    public class SocketUtiles {
        public  static void pringHostAndPort(Socket s){
            Date date = new Date();
            System.out.println(" Local socket Host : "+s.getLocalAddress().getHostName());
            System.out.println(" Local socket HostAddress : "+ s.getLocalAddress().getHostAddress());
            System.out.println(" Local socket Port : "+s.getLocalPort());
            System.out.println("  des socket Host : "+s.getInetAddress().getHostName());
            System.out.println("  des socket HostAddress : "+ s.getInetAddress().getHostAddress());
            System.out.println("  des socket Port : "+s.getPort());
            System.out.println("当前请求时间 "+date.getHours()+" "+date.getMinutes()+date.getSeconds());
        }
    }

    请求客户端会报Exception in thread "main" java.net.ConnectException: Connection refused: connect 拒绝链接。

  • 相关阅读:
    iperf3命令使用
    python 使用多进程无法正常退出
    cfg 4 ocl
    opencv的CMakeLists.txt与makefile写法
    不需要打密码的sudo方法
    Fedora下rstudio-server安装
    Linux下突然不识别无线网卡
    Python使用opencv
    Python version 2.7 required, which was not found in the registry
    MySQL性能优化 — 实践篇1
  • 原文地址:https://www.cnblogs.com/soundcode/p/12171542.html
Copyright © 2011-2022 走看看