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 拒绝链接。

猜你喜欢

转载自blog.csdn.net/qq_29499107/article/details/82868835