day-04 基于UDP的服务器端/客户端

news2025/5/11 5:34:36

一.理解UDP

(一)UDP套接字的特点

UDP套接字具有以下特点:

  • 无连接性:UDP是一种无连接的协议,这意味着在发送数据之前,不需要在发送方和接收方之间建立连接。每个UDP数据包都是独立的,它们可以独立地发送和接收,而不需要维护连接状态。

  • 不可靠性:UDP是一种不可靠的协议,这意味着它不提供数据传输的可靠性保证。UDP数据包在发送过程中可能会丢失、重复、乱序或损坏,而UDP协议本身不提供任何机制来检测和纠正这些问题。因此,应用程序需要自行处理这些问题。

  • 高效性:由于UDP不需要建立连接和维护连接状态,它的开销比TCP更小,传输效率更高。UDP适用于那些对实时性要求较高,但对数据可靠性要求相对较低的应用场景,如音频和视频流传输。

  • 面向数据报:UDP是一种面向数据报的协议,每个UDP数据包都是一个独立的数据报,具有固定的大小。UDP数据包的大小限制为64KB,超过这个大小的数据需要进行分片和重新组装。

  • 支持多播和广播:UDP支持多播和广播功能,可以将数据同时发送给多个接收方。多播是一种一对多的通信方式,广播是一种一对所有的通信方式。

        总的来说,UDP套接字具有无连接性、不可靠性、高效性、面向数据报和支持多播和广播等特点。它适用于那些对实时性要求较高,但对数据可靠性要求相对较低的应用场景。

(二)UDP内部工作原理

UDP的内部工作原理如下:

  • 创建套接字:在UDP通信之前,需要创建UDP套接字。套接字是一个网络通信的端点,用于发送和接收数据。通过调用操作系统提供的套接字API,可以创建一个UDP套接字。

  • 绑定端口:在创建UDP套接字后,需要将套接字绑定到一个特定的端口上。这样,其他应用程序就可以通过指定该端口来与UDP套接字进行通信。

  • 发送数据:要发送数据,应用程序将数据写入UDP套接字的发送缓冲区。操作系统将从发送缓冲区中获取数据,并将其封装成UDP数据包。然后,操作系统将UDP数据包发送到目标IP地址和端口。

  • 接收数据:要接收数据,应用程序需要监听UDP套接字。当有UDP数据包到达时,操作系统将从网络中接收数据包,并将其放入UDP套接字的接收缓冲区。应用程序可以从接收缓冲区中读取数据。

  • 处理数据:应用程序可以从接收缓冲区中读取数据,并对数据进行处理。由于UDP是无连接的协议,每个UDP数据包都是独立的,应用程序需要自行处理数据包的顺序、丢失、重复和损坏等问题。

  • 关闭套接字:当UDP通信结束时,应用程序可以关闭UDP套接字,释放相关资源。

        总的来说,UDP的内部工作原理涉及创建套接字、绑定端口、发送数据、接收数据和处理数据等步骤。UDP是一种简单的协议,不提供连接状态维护和可靠性保证,但具有较低的开销和较高的传输效率。

(三)UDP的高效使用

要高效使用UDP,可以考虑以下几点:

  • 数据包大小:UDP数据包的大小限制为64KB,超过这个大小的数据需要进行分片和重新组装。为了提高传输效率,可以尽量减小数据包的大小,避免数据分片和重新组装的开销。

  • 数据压缩:对于需要传输的数据,可以考虑使用数据压缩算法进行压缩,减小数据包的大小。常见的数据压缩算法包括gzip、zlib等。

  • 并发处理:UDP是无连接的协议,每个UDP数据包都是独立的。为了提高处理效率,可以使用多线程或多进程的方式,并发处理接收到的UDP数据包。

  • 丢包处理:由于UDP是不可靠的协议,数据包在传输过程中可能会丢失。为了提高可靠性,可以在应用层实现丢包检测和重传机制。例如,可以使用序列号和确认应答的方式来检测丢包,并进行重传。

  • 超时设置:为了避免数据包长时间滞留在网络中,可以设置合适的超时时间。如果在超时时间内没有收到对应的确认应答,可以进行重传。

  • 流量控制:为了避免发送方发送过多的数据导致接收方无法及时处理,可以实现流量控制机制。例如,可以使用滑动窗口的方式控制发送方的发送速率。

  • 多播和广播:UDP支持多播和广播功能,可以将数据同时发送给多个接收方。通过合理使用多播和广播,可以提高数据传输的效率。

        总的来说,要高效使用UDP,可以考虑数据包大小、数据压缩、并发处理、丢包处理、超时设置、流量控制和多播/广播等方面的优化策略。根据具体的应用场景和需求,可以选择适合的优化方法。

二.实现基于UDP的服务器端/客户端

1.UDP中的服务器端和客户端没有连接

2.UDP服务器端和客户端均只需一个套接字

3.基于UDP的数据I/O函数

基于UDP的数据I/O函数通常使用以下两个函数:

1.sendto():该函数用于向指定的目标地址发送UDP数据包。它的函数原型如下:

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, 
                const struct sockaddr *dest_addr, socklen_t addrlen);

        参数说明:

  • sockfd:UDP套接字的文件描述符。
  • buf:要发送的数据的指针。
  • len:要发送的数据的字节数。
  • flags:发送标志,通常设置为0。
  • dest_addr:目标地址的结构体指针,包括IP地址和端口号。
  • addrlen:目标地址结构体的长度。

        该函数将指定的数据发送到目标地址。如果发送成功,返回发送的字节数;如果发送失败,返回-1,并设置相应的错误码。

2.recvfrom():该函数用于从指定的源地址接收UDP数据包。它的函数原型如下:

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, 
                    struct sockaddr *src_addr, socklen_t *addrlen);

        参数说明:

  • sockfd:UDP套接字的文件描述符。
  • buf:接收数据的缓冲区指针。
  • len:接收数据的最大字节数。
  • flags:接收标志,通常设置为0。
  • src_addr:源地址的结构体指针,用于存储发送方的IP地址和端口号。
  • addrlen:源地址结构体的长度。

        该函数从指定的UDP套接字接收数据,并将数据存储到指定的缓冲区中。如果接收成功,返回接收的字节数;如果接收失败,返回-1,并设置相应的错误码。

4.基于UDP的回声服务器端/客户端

uecho_server.cpp
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUFFER_SIZE 1024

int main() {
    // 创建UDP套接字
    int server_socket = socket(AF_INET, SOCK_DGRAM, 0);

    // 绑定服务器地址和端口
    struct sockaddr_in server_address{};
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
    server_address.sin_port = htons(8888);
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    std::cout << "服务器已启动,等待客户端连接..." << std::endl;

    while (true) {
        // 接收数据
        char buffer[BUFFER_SIZE];
        struct sockaddr_in client_address{};
        socklen_t client_address_length = sizeof(client_address);
        ssize_t received_bytes = recvfrom(server_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_address, &client_address_length);
        buffer[received_bytes] = '\0';
        std::cout << "接收到来自客户端 " << inet_ntoa(client_address.sin_addr) << " 的数据:" << buffer << std::endl;

        // 发送数据回客户端
        sendto(server_socket, buffer, strlen(buffer), 0, (struct sockaddr*)&client_address, client_address_length);
    }

    return 0;
}
uecho_client.cpp
#include <iostream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>

#define BUFFER_SIZE 1024

int main() {
    // 创建UDP套接字
    int client_socket = socket(AF_INET, SOCK_DGRAM, 0);

    // 服务器地址和端口
    struct sockaddr_in server_address{};
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_address.sin_port = htons(8888);

    while (true) {
        // 输入要发送的数据
        char message[BUFFER_SIZE];
        std::cout << "请输入要发送的数据:";
        std::cin.getline(message, BUFFER_SIZE);

        // 发送数据到服务器
        sendto(client_socket, message, strlen(message), 0, (struct sockaddr*)&server_address, sizeof(server_address));

        // 接收服务器返回的数据
        char buffer[BUFFER_SIZE];
        socklen_t server_address_length = sizeof(server_address);
        ssize_t received_bytes = recvfrom(client_socket, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&server_address, &server_address_length);
        buffer[received_bytes] = '\0';
        std::cout << "接收到服务器返回的数据:" << buffer << std::endl;
    }

    return 0;
}

5.UDP的数据传输特性和调用connect函数

        UDP存在数据边界,所以调用几次 sendto 函数去发送,就调用几次 recvfrom 函数去接收。

(1)已连接(connected)UDP套接字和未连接(unconnected)UDP套接字

        sendto 函数的传输阶段

  •         向UDP套接字注册目标IP和端口号
  •         传输数据
  •         删除UDP套接字中注册的目标地址信息

        UDP套接字默认属于未连接套接字。但在对同一主机进行通信时,过多的增删套接字中目标地址信息,很明显显得多余。所以将UDP套接字变成已连接套接字会提高效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/945568.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HSPCIE仿真】输入网表文件(4)常用分析

常用分析 1. 概述2. 直流初始化和工作点分析2.1 电路初始化(.ic)2.2 初始状态语句初始条件语句.IC 和.DCVOLT节点电压设置语句.NODESET 2.2 直流工作点分析(.op)基本语法示例 2.3 直流扫描分析 (.dc)基本语法示例 2.4 其他类型的直流分析 3. 瞬态分析(.TRAN)基本语法示例 4. 其…

CTFhub-文件上传-前端验证

burp 抓包 --> 重发--> 查看源代码 用 GodZilla 生成木马 文件名为 1.php.jsp 上传-->抓包-->改包 (删掉 .jpg) --> 点击 放行 木马文件位置为&#xff1a;http://challenge-f0531d0c27641130.sandbox.ctfhub.com:10800/upload/1.php 用 蚁剑连接 ctfhub{4743b…

【pyqt5界面化工具开发-7】窗口开发-菜单栏窗口QMainWindow

目录 0x00 前言&#xff1a; 一、调用父类的菜单 二、添加菜单内选项 0x00 前言&#xff1a; QWedget 控件和窗口的父类&#xff0c;自由度高(什么都东西都没有)&#xff0c;没有划分菜单、工具栏、状态栏、主窗口 等区域 QMainWindow 是 QWwidget 的子类&#xff0c;包含菜…

【AI】数学基础——高数(函数微分部分)

参考&#xff1a;https://www.bilibili.com/video/BV1mM411r7ko?p1&vd_source260d5bbbf395fd4a9b3e978c7abde437 唐宇迪&#xff1a;机器学习数学基础 文章目录 1.1 函数1.1.1 函数分类1.1.2 常见函数指/对数函数分段函数原函数&反函数sigmod函数Relu函数(非负函数)复…

dvwa文件上传通关及代码分析

文章目录 low等级medium等级high等级Impossible等级 low等级 查看源码&#xff1a; <?phpif( isset( $_POST[ Upload ] ) ) {// Where are we going to be writing to?$target_path DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path . basename( …

uni-search-bar 实现搜索框自动获取焦点

<!-- 基本用法 --> <uni-search-bar confirm"search" input"input" ></uni-search-bar>查看源代码show:true, showSync&#xff1a;true, 都改为true 即可实现

The Cherno——OpenGL

The Cherno——OpenGL 1. 欢迎来到OpenGL OpenGL是一种跨平台的图形接口&#xff08;API&#xff09;&#xff0c;就是一大堆我们能够调用的函数去做一些与图像相关的事情。特殊的是&#xff0c;OpenGL允许我们访问GPU&#xff08;Graphics Processing Unit 图像处理单元&…

CTFHUB_web_密码口令_默认口令

登陆界面如图所示&#xff0c;题目提示默认口令&#xff1a; 查找常用默认口令&#xff1a; 常见web系统默认口令总结 常见网络安全设备弱口令(默认口令) 找到相关内容&#xff1a; 输入用户名密码得到flag

ChatGPT⼊门到精通(4):ChatGPT 为何⽜逼

⼀、通⽤型AI 在我们原始的幻想⾥&#xff0c;AI是基于对海量数据的学习&#xff0c;锻炼出⼀个⽆所不知⽆所不能的模 型&#xff0c;并借助计算机的优势&#xff08;计算速度、并发可能&#xff09;等碾压⼈类。 但我们⽬前的AI&#xff0c;不管是AlphaGo还是图像识别算法&am…

研华I/O板卡 Win10+Qt+Cmake 开发环境搭建

文章目录 一.研华I/O板卡 Win10QtCmake 开发环境搭建 一.研华I/O板卡 Win10QtCmake 开发环境搭建 参考这个链接安装研华I/O板卡驱动程序系统环境变量添加研华板卡dll Qt新建一个c项目 cmakeList.txt中添加研华库文件 cmake_minimum_required(VERSION 3.5)project(advantechDA…

LeetCode(力扣)617. 合并二叉树Python

LeetCode617. 合并二叉树 题目链接代码 题目链接 https://leetcode.cn/problems/merge-two-binary-trees/ 代码 递归 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # …

解决Three.js辉光背景不透明

使用此pass canvas元素的background都能看到 不过相应的辉光颜色和背景颜色不相容的地方看起来颜色会怪一些 如图 不过如果是纯色就没什么问题了 //ts-nocheck /** Author: hongbin* Date: 2023-04-06 11:44:14* LastEditors: hongbin* LastEditTime: 2023-04-06 11:49:23* De…

Node.js crypto模块 加密算法

背景 微信小程序调用飞蛾热敏纸打印机&#xff0c;需要进行参数sig签名校验&#xff0c;使用的是sha1进行加密 // 通过crypto.createHash()函数&#xff0c;创建一个hash实例&#xff0c;但是需要调用md5&#xff0c;sha1&#xff0c;sha256&#xff0c;sha512算法来实现实例的…

python-图片之乐-ASCII 文本图形

ASCII&#xff1a;一个简单的字符编码方案 pillow模块&#xff1a;读取图像&#xff0c;访问底层数据 numpy模块&#xff1a;计算平均值 import sys, random, argparse import numpy as np import math from PIL import Image定义灰度等级和网格 定义两种灰度等级作为全局值…

Git小白入门——了解分布式版本管理和安装

Git是什么&#xff1f; Git是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09; 什么是版本控制系统&#xff1f; 程序员开发过程中&#xff0c;对于每次开发对各种文件的修改、增加、删除&#xff0c;达到预期阶段的一个快照就叫做一个版本。 如果有一…

EVO大赛是什么

价格是你所付出的东西&#xff0c;而价值是你得到的东西 EVO大赛是什么&#xff1f; “EVO”大赛全称“Evolution Championship Series”&#xff0c;是北美最高规格格斗游戏比赛&#xff0c;大赛正式更名后已经连续举办12年&#xff0c;是全世界最大规模的格斗游戏赛事。常见…

Python Qt学习(四)Radio Button

代码 # -*- coding: utf-8 -*-# Form implementation generated from reading ui file D:\Works\Python\Qt\qt_radiobutton.ui # # Created by: PyQt5 UI code generator 5.15.9 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again.…

2023年高教社杯 国赛数学建模思路 - 案例:异常检测

文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…

(笔记四)利用opencv识别标记视频中的目标

预操作&#xff1a; 通过cv2将视频的某一帧图片转为HSV模式&#xff0c;并通过鼠标获取对应区域目标的HSV值&#xff0c;用于后续的目标识别阈值区间的选取 img cv.imread(r"D:\data\123.png") img cv.cvtColor(img, cv.COLOR_BGR2HSV) plt.figure(1), plt.imshow…

科技助力图书馆新趋势:机器人“图书管理员”展风采

原创 | 文 BFT机器人 PART1 机器人“图书管理员”横空出世 随着科技的日新月异&#xff0c;知识的获取变得更加方便快捷&#xff0c;图书馆不再只是借阅书籍的场所&#xff0c;其渐渐演变成了人们社交、休闲、学习的不二之选。在此场景下&#xff0c;“智能化图书馆”的概念深…