【web】计算机网络编程(重点:UDP数据报/TCP流套接字编程)

本文涉及的产品
数据传输服务 DTS,数据同步 small 3个月
推荐场景:
数据库上云
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: ​本文是计算机网络编程初级入门,主要介绍了网络编程的定义、Socket套接字、UDP数据报套接字编程、TCP流套接字编程、理解协议。

【大家好,我是爱干饭的猿,本文是计算机网络编程初级入门,主要介绍了网络编程的定义、Socket套接字、UDP数据报套接字编程、TCP流套接字编程、理解协议。

后续会继续分享计算机网络TCP_IP三次握手、四次挥手及其他重要知识点总结,如果喜欢这篇文章,点个赞👍,关注一下吧】

上一篇文章:《【web】计算机网络原理(重点:TCP/IP五层模型)》


🤞目录🤞

💖1. 网络编程

1.1 什么是网络编程

1.2 网络编程中的基本概念

1. 发送端和接收端

2. 请求和响应

3. 客户端和服务端

💖2. Socket套接字

2.1 概念

2.2 分类

1. 流套接字

2.数据报套接字

3. 原始套接字

2.3 Java数据报套接字通信模型

2.4 Java流套接字通信模型

2.5 Socket编程注意事项

💖3. UDP数据报套接字编程

3.1 DatagramSocket API

DatagramSocket 方法:编辑3.2 DatagramPacket API

3.3 InetSocketAddress API

3.4 示例:UDP请求响应

UDP服务端

UDP客户端

Log 日志

💖4. TCP流套接字编程

4.1 ServerSocket API

4.2 Socket API

4.3 TCP中的长短连接

4.4 示例一:TCP请求响应(短连接)

TCP服务端

TCP客户端

4.5 示例二:TCP请求响应(长连接)

TCP服务端

TCP客户端

4.6 示例三:TCP请求响应(多线程+自定义协议)

TCP服务端

TCP客户端

💖5. 再谈协议

5.1 理解为什么需要协议

5.2 封装/分用 vs 序列化/反序列化

5.3 如何设计协议

1. 对于定长的字段

2. 对于不定长的字段


🧸1. 网络编程

1.1 什么是网络编程

网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。

image.gif编辑

当然,我们只要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。

1.2 网络编程中的基本概念

1. 发送端和接收端

发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。

接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。

收发端:发送端和接收端两端,也简称为收发端。

注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

2. 请求和响应

一般来说,获取一个网络资源,涉及到两次网络数据传输:

第一次:请求数据的发送

第二次:响应数据的发送。

3. 客户端和服务端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。

客户端:获取服务的一方进程,称为客户端。

对于服务来说,一般是提供:

    • 客户端获取服务资源
    • 客户端保存资源在服务端

    🧸2. Socket套接字

    2.1 概念

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

    2.2 分类

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

    1. 流套接字

    使用传输层TCP协议 TCP,即Transmission Control Protocol(传输控制协议),传输层协议。

    特点:

      • 有连接
      • 可靠传输
      • 面向字节流
      • 有接收缓冲区,也有发送缓冲区
      • 大小不限

      对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情 况下,是无边界的数据,可以多次发送,也可以分开多次接收。

      2.数据报套接字

      使用传输层UDP协议 UDP,即User Datagram Protocol(用户数据报协议),传输层协议。

      特点:

        • 无连接
        • 不可靠传输
        • 面向数据报
        • 有接收缓冲区,无发送缓冲区
        • 大小受限:一次最多传输64k

        3. 原始套接字

        原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

        2.3 Java数据报套接字通信模型

        对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数 据报,一次接收全部的数据报。

        java中使用UDP协议通信,主要基于 DatagramSocket 类来创建数据报套接字,并使用 DatagramPacket 作为发送或接收的UDP数据报。对于一次发送及接收UDP数据报的流程如下:

        image.gif编辑

        对于一个服务端来说,重要的是提供多个客户端的请求处理及响应,流程如下:

        image.gif编辑 2.4 Java流套接字通信模型

        image.gif编辑

        2.5 Socket编程注意事项

        1. 客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但真实的场 景,一般都是不同主机。

        2. 注意目的IP和目的端口号,标识了一次数据传输时要发送数据的终点主机和进程

        3. Socket编程我们是使用流套接字和数据报套接字,基于传输层的TCP或UDP协议,但应用层协议, 也需要考虑,这块我们在后续来说明如何设计应用层协议。

        4. 关于端口被占用的问题

        检查端口被占用:在cmd输入 netstat -ano | findstr 端口号 ,则可以显示对应进程的pid。对应端口进程的pid 在任务管理器中,通过pid查找进程。


        🧸3. UDP数据报套接字编程

        3.1 DatagramSocket API

        DatagramSocket 是UDP Socket,用于发送和接收UDP数据报。

        DatagramSocket 构造方法:

        image.gif编辑

        DatagramSocket 方法:image.gif编辑3.2 DatagramPacket API

        DatagramPacket 构造方法:

        image.gif编辑

        DatagramPacket 方法:

        image.gif编辑

        构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创 建。

        3.3 InetSocketAddress API

        InetSocketAddress ( SocketAddress 的子类 )构造方法:

        image.gif编辑

        3.4 示例:UDP请求响应

        UDP服务端

        import java.io.IOException;
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress;
        /**
         * @author haomin
         * @date 2022/09/26 09:56
         **/
        public class Client {
            public static void main(String[] args) throws IOException {
                // 本机-本机
                // 目前服务器在本机: 127.0.0.1
                // 目前服务器的端口是: 8080
                // 本机只发送一次请求
                String word = "apple";
                // 准备发送请求
                String request = "请求格式头\r\n" + word + "请求格式尾\r\n";
                byte[] bytes = request.getBytes("UTF-8");
                DatagramPacket sent = new DatagramPacket(
                        bytes, 0, bytes.length,
                        InetAddress.getLoopbackAddress(),
                        8088
                );
                DatagramSocket socket = new DatagramSocket(9999);
                Log.println("发送请求");
                socket.send(sent);
                byte[] buf = new byte[1024];
                DatagramPacket received = new DatagramPacket(buf, buf.length);
                socket.receive(received);
                int n = received.getLength();
                String response = new String(buf, 0, n, "utf-8");
                System.out.println(response);
            }
        }

        image.gif

        UDP客户端

        import java.io.IOException;
        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress;
        import java.util.Arrays;
        import java.util.HashMap;
        /**
         * @author haomin
         * @date 2022/09/26 09:57
         **/
        public class Server {
            // 1. 可以写在文件中
            // 2. 可以写在数据库中
            private static final HashMap<String, String> map = new HashMap<>();
            static {
                map.put("apple", "苹果");
                map.put("banana", "香蕉");
            }
            public static void main(String[] args) throws IOException {
                DatagramSocket socket = new DatagramSocket(8080);
                while(true){
                    // 1. 读取请求
                    byte[] buf = new byte[1024];
                    DatagramPacket received = new DatagramPacket(buf, buf.length);
                    socket.receive(received); // 服务器会阻塞在这
                    // 2. 处理
                    InetAddress address = received.getAddress(); // 获得ip
                    int port = received.getPort();               // 获得端口
                    int n = received.getLength();                // 真正收到的数据长度
                    byte[] actualData = Arrays.copyOf(buf, n);   // 真正有用的数据
                    // byte[] + 字符集编码 -> String
                    String request = new String(actualData, 0, actualData.length, "utf-8");
                    // 3. 分析请求
                    if(!request.startsWith("请求格式头\r\n") && !request.startsWith("请求格式尾\r\n")){
                        continue; // 不符合应用层的请求协议,不做处理
                    }
                    String englishWord = request.substring("请求格式头\r\n".length(), request.length() - "请求格式尾\r\n".length());
                    Log.println(englishWord);
                    String chineseWord = map.getOrDefault(englishWord, "不认识");
                    // 4. 发送响应
                    String response = String.format("收到,响应为\r\n%s\r\n", chineseWord);
                    // String + 字符集编码 -> byte[]
                    byte[] bytes = response.getBytes("utf-8");
                    DatagramPacket sent = new DatagramPacket(
                            bytes, 0, bytes.length,
                            address,
                            port
                    );
                    socket.send(sent);
                    Log.println("响应成功"+response);
                }
            }
        }

        image.gif

        Log 日志

        import java.text.DateFormat;
        import java.text.SimpleDateFormat;
        import java.util.Date;
        /**
         * @author haomin
         * @date 2022/09/26 10:30
         **/
        public class Log {
            public static void println(Object o){
                Date date = new Date();
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                String now = dateFormat.format(date);
                System.out.println(now + ": " + o.toString());
            }
            public static void print(Object o){
                Date date = new Date();
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                String now = dateFormat.format(date);
                System.out.print(now +": "+ o.toString());
            }
            public static void printf(String fmt, Object... args){
                Date date = new Date();
                DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                String now = dateFormat.format(date);
                System.out.printf(now + ": " + fmt, args);
            }
            public static void main(String[] args) {
                println("hello word");
                print("hello word\r\n");
                printf("%s","hello word");
            }
        }

        image.gif


        🧸4. TCP流套接字编程

        和刚才UDP类似,实现一个简单的英译汉的功能

        4.1 ServerSocket API

        ServerSocket 是创建TCP服务端Socket的API。

        ServerSocket 构造方法:

        image.gif编辑

        ServerSocket 方法:

        image.gif编辑4.2 Socket API

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

        不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

        Socket 构造方法:

        image.gif编辑

        Socket 方法:

        image.gif编辑

        4.3 TCP中的长短连接

        TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

        长连接:拨通电话->请求->响应->请求->响应->...->请求->响应->挂断电话

        短连接:拨通电话->请求->响应->挂断电话->拨通电话->请求->响应->挂断电话...


        对比以上长短连接,两者区别如下:

          • 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
          • 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
          • 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

          4.4 示例一:TCP请求响应(短连接)

          TCP服务端

          import java.io.*;
          import java.net.InetAddress;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.HashMap;
          import java.util.Scanner;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          // UDP: 无连接       面向数据报文-写信(一信一送)
          // TCP: 有连接       面向字节流  -写信(一堆信一送)-打电话(连接好才行)
          public class Server {
              private static final HashMap<String, String> map = new HashMap<>();
              static {
                  map.put("apple", "苹果");
                  map.put("banana", "香蕉");
              }
              public static void main(String[] args) throws IOException {
                  ServerSocket serverSocket = new ServerSocket(8080);
                  while (true){
                      // 1. 接通连接(电话) —— accept
                      Socket socket = serverSocket.accept(); // 阻塞
                      InetAddress inetAddress = socket.getInetAddress(); // 得到客户端地址
                      int port = socket.getPort();                       // 得到客户端端口
                      InputStream is = socket.getInputStream();  // is: 用于读数据
                      OutputStream os = socket.getOutputStream();// os: 用于写数据
                      // 2. 读取请求
                      Scanner scanner = new Scanner(is, "utf-8");
                      String header = scanner.nextLine();
                      String englishWord = scanner.nextLine();
                      // 3. 处理业务
                      String chineseWord = map.getOrDefault(englishWord, "不认识");
                      // 4. 发送响应
                      // 好的\r\n苹果\r\n
                      // OutputStream -> OutputStreamWriter -> PrintWriter
                      OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                      PrintWriter printWriter = new PrintWriter(writer);
                      printWriter.printf("好的\r\n%s\r\n", chineseWord);
                      printWriter.flush();
                      socket.close();
                      Log.println("服务器响应成功");
                  }
              }
          }

          image.gif

          TCP客户端

          import java.io.*;
          import java.net.Socket;
          import java.util.Scanner;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          public class 短连接Client {
              public static void main(String[] args) throws IOException {
                  while (true) {
                      Socket socket = new Socket("127.0.0.1", 8080);
                      InputStream is = socket.getInputStream();
                      Scanner scanner = new Scanner(is, "utf-8");
                      OutputStream os = socket.getOutputStream();
                      OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                      PrintWriter printWriter = new PrintWriter(writer);
                      // 发送请求
                      printWriter.println("我是Java19班的\r\nbanana\r\n");
                      printWriter.flush();
                      // 读取响应
                      String header = scanner.nextLine();
                      String chineseWord = scanner.nextLine();
                      System.out.println("响应结果:" + chineseWord);
                      socket.close();
                  }
              }
          }

          image.gif

          4.5 示例二:TCP请求响应(长连接)

          TCP服务端

          import java.io.*;
          import java.net.InetAddress;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.HashMap;
          import java.util.Scanner;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          // UDP: 无连接       面向数据报文-写信(一信一送)
          // TCP: 有连接       面向字节流  -写信(一堆信一送)-打电话(连接好才行)
          public class 长连接Server {
              private static final HashMap<String, String> map = new HashMap<>();
              static {
                  map.put("apple", "苹果");
                  map.put("banana", "香蕉");
              }
              public static void main(String[] args) throws IOException {
                  ServerSocket serverSocket = new ServerSocket(8080);
                  while (true){
                      // 1. 接通连接(电话) —— accept
                      Socket socket = serverSocket.accept(); // 阻塞
                      InetAddress inetAddress = socket.getInetAddress(); // 得到客户端地址
                      int port = socket.getPort();                       // 得到客户端端口
                      InputStream is = socket.getInputStream();  // is: 用于读数据
                      OutputStream os = socket.getOutputStream();// os: 用于写数据
                      // OutputStream -> OutputStreamWriter -> PrintWriter
                      OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                      PrintWriter printWriter = new PrintWriter(writer);
                      // 2. 读取请求
                      Scanner scanner = new Scanner(is, "utf-8");
                      while (scanner.hasNextLine()) {
                          String header = scanner.nextLine();
                          String englishWord = scanner.nextLine();
                          // 3. 处理业务
                          String chineseWord = map.getOrDefault(englishWord, "不认识");
                          // 4. 发送响应
                          // 好的\r\n苹果\r\n
                          printWriter.printf("好的\r\n%s\r\n", chineseWord);
                          printWriter.flush();
                          Log.println("服务器响应成功");
                      }
                      socket.close();
                  }
              }
          }

          image.gif

          TCP客户端

          import java.io.*;
          import java.net.Socket;
          import java.util.Scanner;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          public class 长连接Client {
              public static void main(String[] args) throws IOException {
                  Socket socket = new Socket("127.0.0.1", 8080);
                  for (int i = 0; i < 3; i++) {
                      InputStream is = socket.getInputStream();
                      Scanner scanner = new Scanner(is, "utf-8");
                      OutputStream os = socket.getOutputStream();
                      OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                      PrintWriter printWriter = new PrintWriter(writer);
                      // 发送请求
                      printWriter.printf("我是Java19班的\r\napple\r\n");
                      printWriter.flush();
                      // 读取响应
                      String header = scanner.nextLine();
                      String chineseWord = scanner.nextLine();
                      System.out.println("响应结果:" + chineseWord);
                  }
                  socket.close();
              }
          }

          image.gif

          4.6 示例三:TCP请求响应(多线程+自定义协议)

          TCP服务端

          import java.io.*;
          import java.net.InetAddress;
          import java.net.ServerSocket;
          import java.net.Socket;
          import java.util.HashMap;
          import java.util.Scanner;
          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          // UDP: 无连接       面向数据报文-写信(一信一送)
          // TCP: 有连接       面向字节流  -写信(一堆信一送)-打电话(连接好才行)
          public class 多线程长连接Server {
              private static final HashMap<String, String> map = new HashMap<>();
              static {
                  map.put("apple", "苹果");
                  map.put("banana", "香蕉");
              }
              private static class ServerTask implements Runnable{
                  private final Socket socket;
                  private ServerTask(Socket socket){
                      this.socket = socket;
                  }
                  @Override
                  public void run() {
                      try {
                          InetAddress inetAddress = socket.getInetAddress(); // 得到客户端地址
                          int port = socket.getPort();                       // 得到客户端端口
                          InputStream is = socket.getInputStream();  // is: 用于读数据
                          OutputStream os = socket.getOutputStream();// os: 用于写数据
                          // OutputStream -> OutputStreamWriter -> PrintWriter
                          OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                          PrintWriter printWriter = new PrintWriter(writer);
                          // 2. 读取请求
                          Scanner scanner = new Scanner(is, "utf-8");
                          while (scanner.hasNextLine()) {
                              String header = scanner.nextLine();
                              String englishWord = scanner.nextLine();
                              // 3. 处理业务
                              String chineseWord = map.getOrDefault(englishWord, "不认识");
                              // 4. 发送响应
                              // 好的\r\n苹果\r\n
                              printWriter.printf("好的\r\n%s\r\n", chineseWord);
                              printWriter.flush();
                              Log.println("服务器响应成功");
                          }
                          socket.close();
                      }catch (Exception e){
                          e.printStackTrace();
                      }
                  }
              }
              public static void main(String[] args) throws IOException {
                  ExecutorService service = Executors.newFixedThreadPool(10);
                  ServerSocket serverSocket = new ServerSocket(8080);
                  while (true){
                      // 1. 接通连接(电话) —— accept
                      Socket socket = serverSocket.accept(); // 阻塞
                      ServerTask task = new ServerTask(socket);
                      service.execute(task);
                  }
              }
          }

          image.gif

          TCP客户端

          import java.io.*;
          import java.net.Socket;
          import java.util.Scanner;
          /**
           * @author haomin
           * @date 2022/09/27 18:33
           **/
          public class 长连接子输入Client {
              public static void main(String[] args) throws IOException {
                  Socket socket = new Socket("127.0.0.1", 8080);
                  Scanner systemInSc = new Scanner(System.in);
                  while (systemInSc.hasNextLine()){
                      String w = systemInSc.nextLine();
                      InputStream is = socket.getInputStream();
                      Scanner scanner = new Scanner(is, "utf-8");
                      OutputStream os = socket.getOutputStream();
                      OutputStreamWriter writer = new OutputStreamWriter(os, "utf-8");
                      PrintWriter printWriter = new PrintWriter(writer);
                      // 发送请求
                      printWriter.printf("我是Java19班的\r\n%s\r\n", w);
                      printWriter.flush();
                      // 读取响应
                      String header = scanner.nextLine();
                      String chineseWord = scanner.nextLine();
                      System.out.println("响应结果:" + chineseWord);
                  }
                  socket.close();
              }
          }

          image.gif


          🧸5. 再谈协议

          5.1 理解为什么需要协议

          以上我们实现的UDP和TCP数据传输,除了UDP和TCP协议外,程序还存在应用层自定义协议,可以想想分别都是什么样的协议格式。

          对于客户端及服务端应用程序来说,请求和响应,需要约定一致的数据格式:

            • 客户端发送请求和服务端解析请求要使用相同的数据格式。
            • 服务端返回响应和客户端解析响应也要使用相同的数据格式。
            • 请求格式和响应格式可以相同,也可以不同。
            • 约定相同的数据格式,主要目的是为了让接收端在解析的时候明确如何解析数据中的各个字段。
            • 可以使用知名协议(广泛使用的协议格式),如果想自己约定数据格式,就属于自定义协议。

            5.2 封装/分用 vs 序列化/反序列化

            一般来说,在网络数据传输中,发送端应用程序,发送数据时的数据转换(如java一般就是将对象转换为某种协议格式)

            对发送数据时的数据包装动作来说:

              • 如果是使用知名协议,这个动作也称为封装
              • 如果是使用小众协议(包括自定义协议),这个动作也称为序列化,一般是将程序中的对象转换为特定的数据格式。

              接收端应用程序,接收数据时的数据转换,即对接收数据时的数据解析动作来说:

                • 如果是使用知名协议,这个动作也称为分用
                • 如果是使用小众协议(包括自定义协议),这个动作也称为反序列化,一般是基于接收数据特定的格式,转换为程序中的对象

                5.3 如何设计协议

                对于协议来说,重点需要约定好如何解析,一般是根据字段的特点来设计协议:

                1. 对于定长的字段

                可以基于长度约定,如int字段,约定好4个字节即可

                2. 对于不定长的字段

                  • a. 先发送长度+真正的请求[ 18 + ...]
                  • b. 使用特殊字符区分不同的请求比如:每读到两次\rln 一个请求

                  分享到此,感谢大家观看!!!

                  如果你喜欢这篇文章,请点赞关注吧,或者如果你对文章有什么困惑,可以私信我。

                  🏓🏓🏓

                  相关实践学习
                  如何在云端创建MySQL数据库
                  开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
                  Sqoop 企业级大数据迁移方案实战
                  Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
                  相关文章
                  |
                  8天前
                  |
                  网络协议 算法 网络性能优化
                  C语言 网络编程(十五)套接字选项设置
                  `setsockopt()`函数用于设置套接字选项,如重复使用地址(`SO_REUSEADDR`)、端口(`SO_REUSEPORT`)及超时时间(`SO_RCVTIMEO`)。其参数包括套接字描述符、协议级别、选项名称、选项值及其长度。成功返回0,失败返回-1并设置`errno`。示例展示了如何创建TCP服务器并设置相关选项。配套的`getsockopt()`函数用于获取这些选项的值。
                  |
                  8天前
                  |
                  C语言
                  C语言 网络编程(八)并发的UDP服务端 以进程完成功能
                  这段代码展示了如何使用多进程处理 UDP 客户端和服务端通信。客户端通过发送登录请求与服务端建立连接,并与服务端新建的子进程进行数据交换。服务端则负责接收请求,验证登录信息,并创建子进程处理客户端的具体请求。子进程会创建一个新的套接字与客户端通信,实现数据收发功能。此方案有效利用了多进程的优势,提高了系统的并发处理能力。
                  |
                  8天前
                  |
                  C语言
                  C语言 网络编程(七)UDP通信创建流程
                  本文档详细介绍了使用 UDP 协议进行通信的过程,包括创建套接字、发送与接收消息等关键步骤。首先,通过 `socket()` 函数创建套接字,并设置相应的参数。接着,使用 `sendto()` 函数向指定地址发送数据。为了绑定地址,需要调用 `bind()` 函数。接收端则通过 `recvfrom()` 函数接收数据并获取发送方的地址信息。文档还提供了完整的代码示例,展示了如何实现 UDP 的发送端和服务端功能。
                  |
                  8天前
                  |
                  C语言
                  C语言 网络编程(九)并发的UDP服务端 以线程完成功能
                  这是一个基于UDP协议的客户端和服务端程序,其中服务端采用多线程并发处理客户端请求。客户端通过UDP向服务端发送登录请求,并根据登录结果与服务端的新子线程进行后续交互。服务端在主线程中接收客户端请求并创建新线程处理登录验证及后续通信,子线程创建新的套接字并与客户端进行数据交换。该程序展示了如何利用线程和UDP实现简单的并发服务器架构。
                  |
                  8天前
                  |
                  网络协议 视频直播 C语言
                  C语言 网络编程(三)UDP 协议
                  UDP(用户数据报协议)是一种无需建立连接的通信协议,适用于高效率的数据传输,但不保证数据的可靠性。其特点是无连接、尽力交付且面向报文,具备较高的实时性。UDP广泛应用于视频会议、实时多媒体通信、直播及DNS查询等场景,并被许多即时通讯软件和服务(如MSN/QQ/Skype、流媒体、VoIP等)采用进行实时数据传输。UDP报文由首部和数据部分组成,首部包含源端口、目的端口、长度和校验和字段。相比TCP,UDP具有更高的传输效率和更低的资源消耗。
                  |
                  8天前
                  |
                  Java API Apache
                  从零到英雄的蜕变:如何用Apache Wicket打造你的第一个Web应用——不仅是教程,更是编程之旅的启航
                  【9月更文挑战第4天】学习Apache Wicket这一开源Java Web应用框架是一段激动人心的旅程。本文将指导你通过Maven搭建环境,并创建首个“Hello, World!”应用。从配置`pom.xml`到实现`HelloWorldApplication`类,再到`web.xml`的设置,一步步教你构建与部署简单网页。适合初学者快速上手,体验其简洁API与强大组件化设计的魅力。
                  9 1
                  |
                  5天前
                  |
                  网络协议
                  网络协议概览:HTTP、UDP、TCP与IP
                  理解这些基本的网络协议对于任何网络专业人员都是至关重要的,它们不仅是网络通信的基础,也是构建更复杂网络服务和应用的基石。网络技术的不断发展可能会带来新的协议和标准,但这些基本协议的核心概念和原理将继续是理解和创新网络技术的关键。
                  13 0
                  |
                  11天前
                  |
                  物联网 C# 智能硬件
                  智能家居新篇章:WPF与物联网的智慧碰撞——通过MQTT协议连接与控制智能设备,打造现代科技生活的完美体验
                  【8月更文挑战第31天】物联网(IoT)技术的发展使智能家居设备成为现代家庭的一部分。通过物联网,家用电器和传感器可以互联互通,实现远程控制和状态监测等功能。本文将探讨如何在Windows Presentation Foundation(WPF)应用中集成物联网技术,通过具体示例代码展示其实现过程。文章首先介绍了MQTT协议及其在智能家居中的应用,并详细描述了使用Wi-Fi连接方式的原因。随后,通过安装Paho MQTT客户端库并创建MQTT客户端实例,演示了如何编写一个简单的WPF应用程序来控制智能灯泡。
                  26 0
                  |
                  11天前
                  |
                  Java 数据库 API
                  JSF与JPA的史诗级联盟:如何编织数据持久化的华丽织锦,重塑Web应用的荣耀
                  【8月更文挑战第31天】JavaServer Faces (JSF) 和 Java Persistence API (JPA) 分别是构建Java Web应用的用户界面组件框架和持久化标准。结合使用JSF与JPA,能够打造强大的数据驱动Web应用。首先,通过定义实体类(如`User`)和配置`persistence.xml`来设置JPA环境。然后,在JSF中利用Managed Bean(如`UserBean`)管理业务逻辑,通过`EntityManager`执行数据持久化操作。
                  21 0
                  |
                  11天前
                  |
                  Java 开发者 关系型数据库
                  JSF与AWS的神秘之旅:如何在云端部署JSF应用,让你的Web应用如虎添翼?
                  【8月更文挑战第31天】在云计算蓬勃发展的今天,AWS已成为企业级应用的首选平台。本文探讨了在AWS上部署JSF(JavaServer Faces)应用的方法,这是一种广泛使用的Java Web框架。通过了解并利用AWS的基础设施与服务,如EC2、RDS 和 S3,开发者能够高效地部署和管理JSF应用。文章还提供了具体的部署步骤示例,并讨论了使用AWS可能遇到的挑战及应对策略,帮助开发者更好地利用AWS的强大功能,提升Web应用开发效率。
                  35 0