网络编程和Socket套接字(UDP+TCP)(如果想知道Java中有关网络编程和Socket套接字的知识,那么只看这一篇就足够了!)

2025-04-29 0 920

        前言:在当今互联网时代,网络已经成为我们生活和工作中不可或缺的一部分,从浏览网页、在线购物到视频通话、网络游戏,几乎所有的软件都离不开网络通信,网络编程就是让计算机能够通过网络相互交流,实现数据的传输和处理。


网络编程和Socket套接字(UDP+TCP)(如果想知道Java中有关网络编程和Socket套接字的知识,那么只看这一篇就足够了!)

✨✨✨这里是秋刀鱼不做梦的BLOG

✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客

在正式开始讲解之前,先让我们看一下本文大致的讲解内容:

网络编程和Socket套接字(UDP+TCP)(如果想知道Java中有关网络编程和Socket套接字的知识,那么只看这一篇就足够了!)

目录

1.网络编程简介

        (1)什么是网络编程

        (2)为什么需要网络编程

2.网络编程中的基本概念

        (1)发送端和接收端

        (2)请求和响应

        (3)客户端和服务端

3.Socket套接字

        (1)Socket套接字的概念:

        (2)Socket套接字的分类:

        (3)UDP数据报套接字

        (4)TCP流套接字

总结


1.网络编程简介

        首先让我们先了解一下一些有关网络编程的知识:

        (1)什么是网络编程

        网络编程简单来说,就是让不同的设备(电脑、手机、服务器等)通过网络互相交流,它就像是让两个人通过电话、短信或者邮件沟通一样,只不过这里的“电话”是互联网,沟通的是数据。

——我们可以把网络编程比喻成“送快递”:

  1. 你(客户端)在某个购物网站下单(请求)。
  2. 购物网站(服务器)收到订单后,准备商品并打包(处理数据)。
  3. 快递员(网络)把包裹送到你手上(响应)。

        在网络编程中,客户端(你的设备)和服务器(淘宝服务器)需要相互沟通,而这就需要特定的“语言”和“规则”,这些规则就是网络协议(比如TCP和UDP),而网络编程的核心,就是通过这些协议,让计算机能够数据的收和发。

        

        (2)为什么需要网络编程

        想象一下,如果你的电脑或手机不能上网,那会是什么样子?你无法浏览网页、无法聊天、无法看视频、也无法在线购物,现代社会几乎所有的软件和应用都依赖网络,比如微信、淘宝、视频网站、在线游戏等等,网络编程就是让计算机能够通过网络相互通信,让我们可以实现这些功能,至此我们可以看出,有关网络相关的编程时至关重要的!

2.网络编程中的基本概念

        了解完了有关网络的相关介绍之后,不知道你是否对学习有关网络的编程提起了一定的兴趣呢?如果有的话,那么我们继续向下学习。

        ——这里我们需要了解一些有关网络编程中的基本概念:

        (1)发送端和接收端

        在一次网络数据传输中,发送端是指数据的发送方进程,接收端是指数据的接收方进程,发送端主机是网络通信中的源头主机,接收端主机是目的主机,这里我们需要注意的是,发送端和接收端是相对的,要根据一次数据传输中根据数据流向来进行判断。

        (2)请求和响应

        获取一个网络资源通常涉及两次网络数据传输:第一次是请求数据的发送,第二次是响应数据的发送,这个过程就好像快餐店点餐,用户先发起请求(比如点一份炒饭),然后快餐店再提供对应的响应(提供一份炒饭)

        (3)客户端和服务端

        在网络数据传输场景下,提供服务的一方进程称为服务端,获取服务的一方进程称为客户端,服务端通常提供资源的存储和访问服务,而客户端则通过请求获取这些资源,这里我们使用银行举个例子,银行提供存款和取款服务,而用户(客户端)可以通过服务端(银行)保存或获取资源(现金)

        ——通过上面的简短描述,我们应该就大致的了解了发送端和接收端、请求和响应、客户端和服务端都是什么了,那么接下来就让我们学习本文的重点——Socket套接字吧!

3.Socket套接字

        (1)Socket套接字的概念:

        Socket套接字是由系统提供的用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元,基于Socket套接字的网络程序开发就是网络编程。

       

        (2)Socket套接字的分类:

        ——Socket套接字主要针对传输层协议划分为三类:

  • 流套接字:即传输层TCP协议,而TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。
  • 数据报套接字:即传输层UDP协议。而UDP(User Datagram Protocol)是一种无连接的、不可靠的、面向数据报的传输层协议。
  • 原始套接字:即自定义传输层协议,其读写内核没有处理的IP协议数据。

        虽然Socket套接字被分为三类,但是本文主要对UDP和TCP进行讲解!!!

        

        (3)UDP数据报套接字

        ——首先先让我们看一下Java中的UDP相关的API:

  • DatagramSocket:用于发送和接收UDP数据报。

    • DatagramSocket():创建一个UDP数据报套接字,绑定到本机任意一个随机端口(一般用于客户端)。
    • DatagramSocket(int port):创建一个UDP数据报套接字,绑定到本机指定的端口(一般用于服务端)。
    • void receive(DatagramPacket p):从此套接字接收数据报。
    • void send(DatagramPacket p):从此套接字发送数据报包。
    • void close():关闭此数据报套接字。
  • ​DatagramPacket:用于发送和接收UDP数据报。

    • DatagramPacket(byte[] buf, int length):构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组中。
    • DatagramPacket(byte[] buf, int offset, int length, SocketAddress address):构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组中从0到指定长度,address用于指定目的主机的IP和端口号。

        我相信读者在耐心的读完上述的Java中有关UDP的API之后,会对它们如何真实的使用产生疑惑,那么让我们使用一个真实的案例来帮助你进行进一步的理解‘:

以下是使用UDP实现的服务端和客户端代码:

UDP 回显服务器

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UdpEchoServer {
    private DatagramSocket socket = null;

    // 服务器绑定端口
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    // 启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动!");

        while (true) {
            // 1. 读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);

            // 获取客户端发送的数据
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());

            // 2. 计算响应(这里是回显,所以直接返回原数据)
            String response = process(request);

            // 3. 发送响应
            DatagramPacket responsePacket = new DatagramPacket(
                    response.getBytes(),
                    response.getBytes().length,
                    requestPacket.getSocketAddress()
            );
            socket.send(responsePacket);

            // 记录日志,方便观察
            System.out.printf("[%s:%d] req: %s, resp: %s\\n",
                    requestPacket.getAddress().toString(),
                    requestPacket.getPort(),
                    request,
                    response);
        }
    }

    // 回显逻辑,直接返回请求的内容
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}

UDP 回显客户端

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp;
    private int serverPort;

    // 构造方法:指定服务器的 IP 和端口
    public UdpEchoClient(String ip, int port) throws SocketException {
        serverIp = ip;
        serverPort = port;
        // 让系统自动分配客户端端口
        socket = new DatagramSocket();
    }

    // 启动客户端
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("客户端启动!");

        while (true) {
            // 1. 读取用户输入
            System.out.print("-> ");
            String request = scanner.nextLine();  // 使用 nextLine() 以支持输入多词句

            // 2. 发送数据给服务器
            DatagramPacket requestPacket = new DatagramPacket(
                    request.getBytes(),
                    request.getBytes().length,
                    InetAddress.getByName(serverIp),
                    serverPort
            );
            socket.send(requestPacket);

            // 3. 接收服务器响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);

            // 解析响应数据
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());

            // 4. 显示服务器返回的数据
            System.out.println("服务器响应:" + response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}

        ——通过上述案例,相信读者对UDP有了一定的了解了!!!

        (4)TCP流套接字

      ——学习完了UDP套接字之后,再让我们看一下Java中的TCP相关的API:

​ServerSocket:用于创建TCP服务端Socket:

  • ServerSocket(int port):创建一个服务端流套接字Socket,并绑定到指定端口。
  • Socket accept():开始监听指定端口,有客户端连接后,返回一个服务端Socket对象
  • void close():关闭此套接字。

Socket:用于客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket

  • Socket(String host, int port):创建一个客户端流套接字Socket,并与对应IP的主机上对应端口的进程建立连接。
  • InetAddress getInetAddress():返回套接字所连接的地址。
  • InputStream getInputStream():返回此套接字的输入流。
  • OutputStream getOutputStream():返回此套接字的输出流。

        同样,为了让读者能更好的理解上述的API,我们也是使用服务端和客户端的例子进行讲解,只不过我们这次使用TCP流套接字

TCP 回显服务器

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    // 绑定端口号
    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    // 启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动!");
        while (true) {
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }

    // 处理连接逻辑
    private void processConnection(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端上线!\\n", 
            clientSocket.getInetAddress(), clientSocket.getPort());

        // 获取输入输出流
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream();
             Scanner scanner = new Scanner(inputStream);
             PrintWriter writer = new PrintWriter(outputStream, true)) {

            // 处理多次请求
            while (scanner.hasNext()) {
                // 1. 读取请求
                String request = scanner.next();
                // 2. 计算响应
                String response = process(request);
                // 3. 发送响应
                writer.println(response);

                // 打印日志
                System.out.printf("[%s:%d] req: %s, resp: %s\\n",
                    clientSocket.getInetAddress(), clientSocket.getPort(), request, response);
            }

            System.out.printf("[%s:%d] 客户端下线!\\n", 
                clientSocket.getInetAddress(), clientSocket.getPort());

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 确保关闭 socket
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 业务逻辑:回显请求
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}

TCP 回显客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket;

    // 构造函数:连接到服务器
    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        socket = new Socket(serverIp, serverPort);
    }

    // 启动客户端
    public void start() {
        System.out.println("客户端启动");

        // 控制台输入流
        Scanner scannerConsole = new Scanner(System.in);

        try (
            InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();
            Scanner scannerNetwork = new Scanner(inputStream);
            PrintWriter printWriter = new PrintWriter(outputStream, true) // 自动刷新
        ) {
            while (true) {
                // 1. 从控制台读取输入
                System.out.print("-> ");
                String request = scannerConsole.nextLine();

                // 用户输入 exit 退出客户端
                if ("exit".equalsIgnoreCase(request)) {
                    System.out.println("客户端退出...");
                    break;
                }

                // 2. 发送请求到服务器
                printWriter.println(request);

                // 3. 读取服务器的响应
                if (scannerNetwork.hasNextLine()) {
                    String response = scannerNetwork.nextLine();
                    // 4. 输出响应
                    System.out.println("服务器响应: " + response);
                } else {
                    System.out.println("服务器已关闭连接");
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 客户端主函数
    public static void main(String[] args) throws IOException {
        TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);
        client.start();
    }
}

        ——至此,我们使用了TCP实现了服务端和客户端的通信,希望读者能通过上述的案例加深对TCP的API的理解与使用。

总结

        网络编程是通过网络实现进程间通信的技术,核心是Socket套接字,其中Socket分为流套接字(TCP)和数据报套接字(UDP),TCP提供有连接、可靠的字节流传输,适用于需要稳定性的场景,而UDP提供无连接、不可靠的数据报传输,适用于实时性要求高的场景。在网络通信中,客户端发送请求,服务端返回响应,这些都是通过Socket实现数据的收发的。


以上就是本篇文章的全部信息了!!!

平台声明:以上文章转载于《CSDN》,文章全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,仅作参考。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2302_80198073/article/details/146287596

遇见资源网 编程语言 网络编程和Socket套接字(UDP+TCP)(如果想知道Java中有关网络编程和Socket套接字的知识,那么只看这一篇就足够了!) http://www.ox520.com/157774.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务