通过套接字(Socket)建立网络传输管道

计算机网络系列文章,点击上方合集↑

1. 什么是套接字

套接字(Socket)是计算机网络通信中的一种抽象概念,在网络中有两个主机之间进行双向通信的连接点。它允许计算机之间通过网络传输数据,就像电话中的两个通信者在进行对话一样。

想象两个水龙头和一根水管,把水管的两头分别接上这两个水龙头了,水龙头就能通过水管流淌水了。

两个计算机通过套接字就建立了一条传输管道。

通过套接字(Socket)建立网络传输管道

不管是Tcp和Udp或者基于Tcp的Http协议都是通过套接字发送数据。

在套接字中,分为服务端套接字和客户端套接字,服务端通过它本机的IP地址和一个端口生成服务端套接字,客户端基于服务端的提供的服务端IP地址和服务端端口生成客户端套接字,生成客户端套接字的时候操作系统会随机选择一个空闲的端口来给客户端使用。

服务端套接字可以跟很多客户端套接字建立通道,既可以跟不同计算机的相同端口建立通道,也可以跟一个计算机的不同端口建立通道。

2. 计算机端口的范围

端口的范围是0~65535。

系统端口号:范围是0到1023,这些端口号已经被标准化,并且被公认为特定协议或应用程序的默认端口。例如,HTTP协议的默认端口是80,FTP协议的默认端口是21,SSH协议的默认端口是22等。

可用端口:范围是1024到49151,这些端口我们在开发的时候可以直接使用。

动态/私有端口:动态/私有端口号范围是49152到65535,也称为临时端口号。这些端口号可供系统随机选择并分配给客户端应用程序进行临时使用。

3. 查看自己电脑的套接字

通过如下命令可以查看本机的套接字:

netstat -aon
通过套接字(Socket)建立网络传输管道

可以看到本机的端口都很大,这些都是操作系统随机选择的,

4. 通过图例理解套接字

通过套接字(Socket)建立网络传输管道
  • 红框框就是在计算机端口建立的套接字。

计算机B的80端口同时与计算机A的8009端口和计算机C的8080端口建立了通道。

计算机C的8081端口与计算机D的8888端口建立了通道。

5. Java 示例代码

5.1 TCP协议的Socket

Socket需要在客户端和服务器之间建立连接,通信前必须先建立连接,连接建立后才能可以互相发送和接收数据。

public class TCPServer {
    public static void main(String[] args) throws IOException {
        // 创建服务器套接字,绑定端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务器启动,等待客户端连接...");

        // 等待客户端连接
        Socket clientSocket = serverSocket.accept();
        System.out.println("客户端已连接:" + clientSocket.getInetAddress().getHostAddress() + ",端口:" + clientSocket.getPort());

        // 获取输入流和输出流
        BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        PrintWriter output = new PrintWriter(clientSocket.getOutputStream(), true);

        // 监听客户端消息并作出相应
        String message;
        while ((message = input.readLine()) != null) {
            System.out.println("客户端发送的消息:" + message);
            output.println("已收到您的消息:" + message);
        }

        // 关闭连接
        output.close();
        input.close();
        clientSocket.close();
        serverSocket.close();
    }
}
public class TCPClient {
    public static void main(String[] args) throws IOException {
        // 创建客户端套接字,指定服务器地址和端口
        Socket socket = new Socket("localhost"8888);

        // 获取输入流和输出流
        BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        PrintWriter output = new PrintWriter(socket.getOutputStream(), true);

        // 从命令行读取输入的消息并发送给服务器
        BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
        String message;
        while ((message = consoleReader.readLine()) != null) {
            output.println(message);
            System.out.println("已发送给服务器:" + message);

            // 接收服务器的响应并打印
            String response = input.readLine();
            System.out.println("服务器的响应:" + response);
        }

        // 关闭连接
        output.close();
        input.close();
        socket.close();
    }
}

客户端在命令行输入hello world

hello world
已发送给服务器:hello world
服务器的响应:已收到您的消息:hello world

客户端打印如下:

服务器启动,等待客户端连接...
客户端已连接:127.0.0.1,端口:54074
客户端发送的消息:hello world

5.2 UDP协议的DatagramSocket

DatagramSocket不需要在客户端和服务器之间建立连接,直接发送数据包到目标IP地址和端口即可。

public class UDPServer {
    public static void main(String[] args) throws IOException {
        DatagramSocket serverSocket = new DatagramSocket(8888);

        byte[] receiveData = new byte[1024];
        byte[] sendData;

        while (true) {
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);

            serverSocket.receive(receivePacket);

            String message = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("客户端发送的消息:" + message);

            InetAddress clientIPAddress = receivePacket.getAddress();
            int clientPort = receivePacket.getPort();

            String response = "已收到您的消息:" + message;
            sendData = response.getBytes();

            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, clientIPAddress, clientPort);
            serverSocket.send(sendPacket);
        }
    }
}
public class UDPClient {
    public static void main(String[] args) throws IOException {
        DatagramSocket clientSocket = new DatagramSocket();

        InetAddress serverIPAddress = InetAddress.getByName("localhost");
        int serverPort = 8888;

        BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));

        byte[] sendData;
        byte[] receiveData = new byte[1024];

        String message;
        while ((message = consoleReader.readLine()) != null) {
            sendData = message.getBytes();

            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, serverIPAddress, serverPort);
            clientSocket.send(sendPacket);

            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            clientSocket.receive(receivePacket);

            String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("服务器的响应:" + response);
        }

        clientSocket.close();

    }
}

客户端在命令行输入hello world

hello world
服务器的响应:已收到您的消息:hello world

服务端打印如下:

客户端发送的消息:hello world

通过套接字(Socket)建立网络传输管道

关注微信公众号:“小虎哥的技术博客”,让我们一起成为更优秀的程序员❤️!

更多内容点击以下合集:

深入编程原理系列合集

Java 基础系列合集

Java23种设计模式合集

Spring Boot 系列合集

Spring Cloud 微服务系列合集

领域驱动设计系列合集

原文始发于微信公众号(小虎哥的技术博客):通过套接字(Socket)建立网络传输管道

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/169520.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!