当前位置: 首页 > news >正文

Linux编程——网络编程(UDP)

 网络编程——UDP(用户数据报)

udp特征:

1.数据传输不可靠(丢包率);

2.低延迟;

3.网络开销小;

4.无连接        //无连接 意味着在通信双方开始传输数据之前,不需要预先建立一条专用的通信通道(即连接)

数据报特征:

1.数据与数据之间有边界

2.发送的次数和接收的次数需要对应(保持一致)

3.如果发送太快,就会丢包        //原因:硬盘读的快写的慢

操作流程

头文件:#include <sys/types.h>       
#include <sys/socket.h>

              #include <netinet/ip.h>        /* bind() */

              #include <arpa/inet.h>        /* inet_addr() */

服务端:

socket() ==》bind() ==》recvfrom() ==》sendto()

!!!伪代码逻辑

//1.创建一个UDP套接字
socket(AF_INET, SOCK_DGRAM, 0);// 2. 构建服务器地址 (Server Address Setup)
//    (服务器的IP和Port)
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT); // 服务器端口,如8080
inet_addr("ser.ip"); // 服务器IP,如"192.168.1.100"//3.将该套接字绑定到服务器的IP和某个端口(如 8080)
bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); //4.阻塞等待,直到有客户端发来数据。cli_addr 会被填充为客户端的地址信息
recvfrom(sockfd, buf, buf_size, 0, (struct sockaddr*)&cli_addr, &cli_addr_len);//5.处理完请求后,使用 recvfrom 得到的客户端地址 cli_addr,将回复数据发送回去
sendto(sockfd, response_buf, response_len, 0, (struct sockaddr*)&cli_addr, cli_addr_len);

1、socket() 创建通信节点(打开网络设备)

原型:        int socket(int domain, int type, int protocol);

功能:        创建一个通信端点,并返回一个文件描述符(socket descriptor)

参数:        int domain: 指定协议族(Protocol Family)

                   int type: 指定通信语义(套接字类型)

                   int protocol: 通常设置为 0,表示根据 domain 和 type 自动选择默认协议。例如,(AF_INET, SOCK_STREAM) 会自动选择 TCP。

返回值:      成功 返回非负整数文件描述符

                     失败 返回-1,并设置errno

指定协议族:

  • AF_INET: IPv4 协议

  • AF_INET6: IPv6 协议

  • AF_UNIX 或 AF_LOCAL: 本地进程间通信

指定通信定义:

  • SOCK_STREAM: 提供面向连接的、可靠的字节流(TCP)

  • SOCK_DGRAM: 提供无连接的、不可靠的数据报服务(UDP)


2、bind() 给套接字,绑定地址和端口号( ip+port )

原型:        int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

功能:        将一个本地协议地址(IP地址 + 端口号)分配给由 socket() 创建的套接字。服务器程序通常需要调用此函数来将其套接字与一个众所周知的端口号绑定,以便客户端能够连接到服务器

参数:         int sockfdsocket() 函数返回的套接字描述符

                     const struct sockaddr *addr: 指向一个地址结构体的指针,该结构体包含了要绑定的IP和端口号

                      socklen_t addrlen: 第二个参数 addr 所指向结构体的长度(以字节为单位),通常使用 sizeof(struct sockaddr_in)

返回值:      成功 返回0;

                    失败 返回-1,并设置errno

参数二:指向地址结构体的指针:

  • 对于IPv4 (AF_INET),使用 struct sockaddr_in

  • 对于IPv6 (AF_INET6),使用 struct sockaddr_in6

bind伪代码示例
struct sockaddr_in ser,cli;ser.sin_family = AF_INET;//host to net shortser.sin_port = htons(50000);ser.sin_addr.s_addr = inet_addr("192.168.1.200");  int ret = bind(sockfd,(SA)&ser,sizeof(ser));if(-1 == ret){perror("bind fail");return 1;}

3、recvfrom() 从客户端接收数据(阻塞等待客户端请求)

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

功能:        从一个(特别是无连接的,如UDP)套接字接收数据,并捕获发送方的源地址。它是一个阻塞性调用,除非有数据到达,否则调用该函数的进程会被挂起(休眠)

参数:       

  • int sockfd: 套接字描述符。

  • void *buf: 指向接收缓冲区的指针,用于存放接收到的数据。

  • size_t len: 接收缓冲区 buf 的最大长度。

  • int flags: 控制接收行为的标志位,通常设置为 0(表示无特殊行为)。

  • struct sockaddr *src_addr: (输出参数)指向一个 sockaddr 结构体的指针,用于存放发送方的地址信息(IP和端口)。如果不需要知道发送方是谁,可以设置为 NULL

  • socklen_t *addrlen: (输入输出参数)

    • 输入: 指向一个整数,表示 src_addr 指向的缓冲区的大小。

    • 输出: 函数返回时,该整数会被设置为实际存放的地址信息的长度。

返回值:     成功 返回接收到的字节数

                   失败 返回-1,并设置errno

recvfrom伪代码示例

char buf[512] = {0};
recvfrom(sockfd,buf,sizeof(buf),0, (SA)&cli,&len);    //接收客户端数据
printf("recv client:%s\n",buf);

4、sendto() 向套接字发送数据

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

功能:        向一个指定的目标地址发送数据。通常用于无连接的套接字(如UDP),因为每次发送都需要指定目标地址。

参数:        

  • int sockfd: 套接字描述符。

  • const void *buf: 指向发送缓冲区的指针,包含要发送的数据。

  • size_t len: 要发送的数据的字节数。

  • int flags: 控制发送行为的标志位,通常设置为 0

  • const struct sockaddr *dest_addr: 指向一个 sockaddr 结构体的指针,包含了目标接收方的地址信息(IP和端口)。

  • socklen_t addrlen: 第五个参数 dest_addr 所指向结构体的长度。

返回值:     成功 返回实际发送出去的字节数

                   失败 返回-1,并设置errno

sendto伪代码示例

sprintf(buf, "%s %s",buf,ctime(&tm));    //数据处理
sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);    //发送给客户端处理结束的数据

总代码示例

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>typedef struct sockaddr * SA;
int	main(int argc, char **argv)
{int sockfd = socket(AF_INET,SOCK_DGRAM,0);if(-1 == sockfd){perror("socket fail");return 1;}//man 7 ipstruct sockaddr_in ser,cli;ser.sin_family = AF_INET;//host to net shortser.sin_port = htons(50000);ser.sin_addr.s_addr = inet_addr("192.168.1.200");int ret = bind(sockfd,(SA)&ser,sizeof(ser));if(-1 == ret){perror("bind fail");return 1;}time_t tm;socklen_t len = sizeof(cli);while (1){char buf[512] = {0};time(&tm);recvfrom(sockfd,buf,sizeof(buf),0, (SA)&cli,&len);printf("recv client:%s\n",buf);sprintf(buf, "%s %s",buf,ctime(&tm));sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);    }return 0;
}

客户端:

伪代码逻辑

socket() ==》sendto() ==》recvfrom()

//1.创建UDP套接字(Socket Creation)
//  创建一个用于UDP通信的套接字,得到文件描述符sockfd
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);// 2. 构建服务器地址 (Server Address Setup)
//    告诉系统数据要发往哪里(服务器的IP和Port)
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVER_PORT); // 服务器端口,如8080
inet_addr("ser.ip"); // 服务器IP,如"192.168.1.100"// 3. 发送数据 (Sending Data)
//    使用sendto将数据发送到上面指定的serv_addr
sendto(sockfd, request_data, request_len, 0,(struct sockaddr*)&serv_addr, sizeof(serv_addr));// 4. 接收回复 (Receiving Response)
//    使用同一个sockfd接收数据。可以捕获回复方的地址,这里设为NULL表示不关心
recvfrom(sockfd, response_buf, sizeof(response_buf), 0,NULL, NULL); // 不关心回复来自谁,所以后两个参数为NULL

【函数使用方法见上述服务器端!!!】

1、socket() 创建通信节点(打开网络设备)

2、sendto() 向指定目标发送数据

3、recvfrom() 从套接字接收处理后的数据


总示例代码

#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <time.h>
#include <unistd.h>typedef struct sockaddr *SA;
int main(int argc, char **argv)
{int sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (-1 == sockfd){perror("socket fail");return 1;}//struct sockaddr_in ser;ser.sin_family = AF_INET;// host to net shortser.sin_port = htons(50000);ser.sin_addr.s_addr = inet_addr("192.168.1.200");// ser.sin_addr.s_addr = inet_addr("192.168.1.23");int i = 10;while (i--){char buf[512] = {"hello"};sendto(sockfd, buf, strlen(buf), 0, (SA)&ser, sizeof(ser));bzero(buf, sizeof(buf));recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);printf("from ser:%s\n", buf);sleep(1);}return 0;
}

服务器/客户端模型

c/s  b/s

c/s(客户端/服务器模型)b/s(浏览器/服务器模型)
客户端专用/通用客户端专用客户端通用
使用协议http协议自定义协议、标准协议
资源角度资源大部分都在client,server发送必要的交互资源给clientserver发送给client
功能功能可以相对复杂受到http协议的限制,功能不复杂

p2p模型(peer)

在P2P网络中,每个节点(Peer)既是客户端(向其他节点请求服务),也是服务器(为其他节点提供服务)。没有永恒的中心服务器,所有节点地位对等。

一个P2P节点的核心任务是:既要能主动发起请求,也要能被动接收并处理请求。因此,每个节点的流程都融合了客户端和服务器的行为。


文章转载自:

http://6U3jIhya.pxmyw.cn
http://6ITArn78.pxmyw.cn
http://1v9uORnH.pxmyw.cn
http://mAIj7vmT.pxmyw.cn
http://f39fGVfo.pxmyw.cn
http://sMKTE2rG.pxmyw.cn
http://Dhca2SeQ.pxmyw.cn
http://RW2h1vwn.pxmyw.cn
http://zqeshNwZ.pxmyw.cn
http://nBC2IzwR.pxmyw.cn
http://El6tjVyD.pxmyw.cn
http://MSw5JhU9.pxmyw.cn
http://kdfM96eR.pxmyw.cn
http://98xmRXKh.pxmyw.cn
http://8KXdqnQP.pxmyw.cn
http://3YtB81WN.pxmyw.cn
http://5dr0c02W.pxmyw.cn
http://9ucAXBzH.pxmyw.cn
http://kmPv7HmD.pxmyw.cn
http://pRDWp3t3.pxmyw.cn
http://ZIMCugp1.pxmyw.cn
http://l0CaLvAr.pxmyw.cn
http://s0A4WgiI.pxmyw.cn
http://fxrzINRn.pxmyw.cn
http://CKR1YJ2E.pxmyw.cn
http://J32RnhLf.pxmyw.cn
http://YaNNbUzV.pxmyw.cn
http://M9PfafKe.pxmyw.cn
http://JglHhFsz.pxmyw.cn
http://QbpX3O22.pxmyw.cn
http://www.dtcms.com/a/366127.html

相关文章:

  • 当液态玻璃计划遭遇反叛者:一场 iOS 26 界面的暗战
  • 大语言模型推理的幕后英雄:深入解析Prompt Processing工作机制
  • 计算机大数据毕业设计推荐:基于Spark的新能源汽车保有量可视化分析系统
  • 如何轻松地将联系人从 Mac 同步到 iPhone
  • 如何本地编译servicecomb-java-chassis
  • 系统越拆越乱?你可能误解了微服务的本质!
  • 商城源码后端性能优化:JVM 参数调优与内存泄漏排查实战
  • SVN和Git两种版本管理系统对比
  • Clang 编译器:下载安装指南与实用快捷键全解析
  • Java全栈开发面试实录:从基础到微服务的深度探索
  • CentOS系统如何查看当前内存容量
  • SuperSocket 动态协议服务端开发全解析
  • RTSP 协议认证机制详解:Basic 与 Digest 的原理与应用
  • 小迪安全v2023学习笔记(七十七讲)—— 业务设计篇隐私合规检测重定向漏洞资源拒绝服务
  • 【RNN-LSTM-GRU】第四篇 GRU门控循环单元:LSTM的高效替代者与实战指南
  • 为何三折叠手机只有华为可以?看华为Mate XTs非凡大师就知道
  • 2025年09月03日最热门的开源项目(Github)
  • Redis底层实现原理之五大基础结构
  • 云手机与网络游戏相结合的优势?
  • Docker学习笔记(二):镜像与容器管理
  • 20. 云计算-华为云-云服务
  • 域名注册后,为什么还需要域名解析?
  • 嵌入式硬件 - 51单片机3
  • 操作系统(二) :进程与线程
  • 力扣14:最长公共前缀
  • 【面试题】生成式搜索能否保证top-1的准确性?
  • C++类和对象(上):从设计图到摩天大楼的构建艺术
  • 从战略亏损到万亿估值:新“股王”寒武纪如何改写中国芯片叙事?
  • Sentinel 与 Feign 整合详解:实现服务调用的流量防护
  • solar应急响应-7月