网络编程 lesson3 UDP基础编程

news/2024/5/18 14:41:14 标签: udp, 网络, 网络协议

目录

UDP介绍

UDP编程

函数接口

recvfrom

sendto

 小练习:实现服务器和客户端相连(使用UDP实现)

client

server


UDP介绍

UDP(User Datagram Protocol,用户数据报协议)是一种在计算机网络中常用的传输层协议。与TCP(Transmission Control Protocol,传输控制协议)相比,UDP是一种无连接的协议,它提供了一种简单的、无状态的数据传输方式。

下面是UDP的一些关键特点和用途:

  1. 面向无连接:UDP在通信之前不需要建立连接,发送方直接将数据报发送到目标地址。这种无连接的特性使UDP的通信过程更加简洁高效,但也导致了它的不可靠性。

  2. 不可靠性:由于UDP缺乏数据确认、重传机制和流量控制,因此它无法保证数据的可靠性和顺序。数据报可能会丢失、重复、乱序或损坏。这使得UDP在一些对数据完整性要求较低、实时性较高的应用中更为适用,如音频、视频、实时游戏等。

  3. 低延迟:由于UDP的简单性和无连接性,它的处理延迟较低,适用于那些对实时性要求较高的应用场景。例如,音频和视频流媒体通常使用UDP来避免因TCP的拥塞控制机制而引入的较大延迟。

  4. 支持广播和多播:UDP可以向一个特定的IP广播地址或多播地址发送数据报,以实现将数据传输给多个接收方的应用场景,如视频会议、实时流广播等。

  5. 轻量级:相对于TCP,UDP的头部开销较小,传输的数据报包含更少的控制信息。这使得UDP在网络带宽较低或资源有限的环境中更加高效。

UDP被广泛用于许多网络应用中,例如音频和视频流媒体(如VoIP、视频聊天)、实时游戏、DNS(Domain Name System,域名系统)等。尽管UDP具有不可靠性和丢包的风险,但通过适当的应用层协议和机制,可以弥补这些缺点,使UDP在特定的应用场景中发挥重要作用。

UDP编程

 注:上图主要是一种思想,实际编程思路如下

udb流程 (类似短信)

server:
创建数据报套接字 sockt (SOCK_DGRAM)
绑定			bind 	绑定
接收			recvfrom 接收信息
关闭套接字		close

client:
创建数据包套接字 sockt (SOCK_DGRAM)
发送			sendto
关闭套接字		close

函数接口

recvfrom

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
					struct sockaddr *src_addr, socklen_t *addrlen);
功能:接收数据

参数:
	sockfd:套接字描述符
	buf:接收缓存区的首地址
	len:接收缓存区的大小
	flags:0
	src_addr:发送端的网络信息结构体的指针
	addrlen:发送端的网络信息结构体的大小的指针
  
返回值:
	成功接收的字节个数
	失败:-1
	0:客户端退出

sendto

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                  const struct sockaddr *dest_addr, socklen_t addrlen);
功能:发送数据

参数:
	sockfd:套接字描述符
	buf:发送缓存区的首地址
	len:发送缓存区的大小
	flags:0
	src_addr:接收端的网络信息结构体的指针
	addrlen:接收端的网络信息结构体的大小

返回值: 
	成功发送的字节个数
	失败:-1

 小练习:实现服务器和客户端相连(使用UDP实现)

client

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define Port 2065
#define N 128
int main(int argc, char const *argv[])
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(Port);
    saddr.sin_addr.s_addr = INADDR_ANY;

    socklen_t len = sizeof(caddr);

    if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("bind err.");
        return -1;
    }
    char buf[N];
    char q[N];
    //注意这里绑定得是发送段得结构体
    //注意循环位置
    while (1)
    {
        ssize_t recvid = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &len); //这里得0不代表阻塞得意思
        if (recvid < 0)
        {
            perror("recvfrom err.");
            return -1;
        }
        printf("端口:%d\n", ntohs(caddr.sin_port));       //注意这里得转换函数
        printf("IP地址:%s\n", inet_ntoa(caddr.sin_addr)); //将网络字节序得二进制转换为字符型
        printf("%s\n", buf);
        sprintf(q, "recv:%s", buf);
        sendto(sockfd, q, N, 0, (struct sockaddr *)&caddr, len);
    }
    close(sockfd);
    return 0;
}

server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>

#define Port 2065
#define N 128
int main(int argc, char const *argv[])
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        perror("socket err.");
        return -1;
    }
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(Port);
    saddr.sin_addr.s_addr = INADDR_ANY;
    char buf[N];
    socklen_t len = sizeof(saddr);
    while (1)
    {
        fgets(buf, N, stdin);
        if (buf[strlen(buf) - 1] == '\n')
        {
            buf[strlen(buf) - 1] = '\0';
        }
        //绑定接受段得结构体
        sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&saddr, sizeof(saddr));
        recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&saddr, &len);
        printf("%s\n",buf);
    }
    close(sockfd);
    return 0;
}


http://www.niftyadmin.cn/n/322717.html

相关文章

分布式补充技术 01.AOP技术

01.AOP技术是对于面向对象编程&#xff08;OOP&#xff09;的补充。是按照OCP原则进行的编写&#xff0c;(ocp是修改模块权限不行&#xff0c;扩充可以) 02.写一个例子&#xff1a; 创建一个新的java项目&#xff0c;在main主启动类中&#xff0c;写如下代码。 package com.co…

Google Mock 入门

目录 1 概述 1.1 什么是Mock? 1.2 Google Mock概述 1.3 参考文档 2 Google Mock使用 2.1 最简单的例子 2.2 典型的流程 2.3 自定义方法/成员函数的期望行为 2.3.1 Matcher&#xff08;匹配器&#xff09; 2.3.2 基数&#xff08;Cardinalities&#xff09; 2.3.3 行为…

华为杯”研究生数学建模竞赛2021 年中国研究生数学建模竞赛 D 题: 抗乳腺癌候选药物的优化建模-参考思路

一、背景介绍 乳腺癌是目前世界上最常见,致死率较高的癌症之一。乳腺癌的发展与雌激 素受体密切相关,有研究发现,雌激素受体 α 亚型( Estrogen receptors alpha, ERα ) 在不超过 10% 的正常乳腺上皮细胞中表达,但大约在 50%-80% 的乳腺肿瘤细胞 中表达;而对 ER…

Windows10中英文切换按钮消失?一招解决

目录 问题场景&#xff1a; 问题描述 原因分析&#xff1a; 解决方案&#xff1a; 1. 打开设置&#xff0c;选择时间和语言 2. 进入日期时间设置 3. 进入高级键盘设置 4. 勾选这个勾选框&#xff0c;问题解决 问题场景&#xff1a; 博主玩道德与法治V在线模式时&#…

【Leetcode -500.键盘行 -504.七进制数】

Leetcode Leetcode -500.键盘行Leetcode - 504.七进制数 Leetcode -500.键盘行 题目&#xff1a;给你一个字符串数组 words &#xff0c;只返回可以使用在 美式键盘 同一行的字母打印出来的单词。 美式键盘 中&#xff1a; 第一行由字符 “qwertyuiop” 组成。 第二行由字符 …

[架构之路-199] - 可靠性需求与可靠性分析:鱼骨图、故障树分析法FTA、失效模式与影响DFMEA,找到影响故障的主要因素

目录 引言&#xff1a; 第1章 故障树分析法与鱼骨图的比较 1.1 相同点 1.2 区别点 第2章 鱼骨图 第3章 故障树 3.1 示意图 3.2 故障树解读 3.3 故障树常见符号 第4章 产品失效(Failure)模式分析DFMEA 引言&#xff1a; 目标系统/产品的可靠性和性能在客户需求阶段就…

网络编程 lesson4 linux下的IO模型和特点

目录 阻塞式IO 工作流程 非阻塞式IO 工作流程 设置非阻塞IO方法 fcntl实例 信号驱动IO 工作流程 实例&#xff1a;在LINUX下检听自己鼠标的动作 IO多路复用&#xff08;重点&#xff0c;难点&#xff09; 工作流程 本文核心内容&#xff01;&#xff01;&#xff01…

Golang每日一练(leetDay0065) 位1的个数、词频统计

目录 191. 位1的个数 Nnumber of 1-bits &#x1f31f; 192. 统计词频 Word Frequency &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 191. 位1的个数 Nnum…