上海网站设计公司联系方式,公司简介怎么写吸引人,wordpress获取页面的当前位置,新媒体运营网络编程UDP—socket实现 前言UDP客户端和服务端UDP使用场景UDP socket C代码示例服务端接收数据示例#xff08;bindrecvfrom 阻塞式接收信息#xff09;#xff1a;bind 绑定-监听 函数为什么一般都是监听所有网络接口呢#xff1f;为什么需要用inet_addr进行转换#x… 网络编程UDP—socket实现 前言UDP客户端和服务端UDP使用场景UDP socket C代码示例服务端接收数据示例bindrecvfrom 阻塞式接收信息bind 绑定-监听 函数为什么一般都是监听所有网络接口呢为什么需要用inet_addr进行转换 socket函数sockaddr_in结构体recvfrom 函数 客户端发送数据示例sendto 发送 函数 前言 UDP通信需要哪些必要信息 IP地址 用于定位通讯双方 端口号 用于标识通信的具体应用或服务。传输层通信都需要端口号的。 网络要求 双方必须是可以进行ip通信的 UDP依赖IP协议栈IPv4或IPv6完成路由、传输 双方需要用同一协议
UDP客户端和服务端 客户端 构造数据报包含目标IP、目标端口、数据内容。 发送数据报使用套接字 sendto() 函数将数据发送到目标地址。 等待响应如果有接收服务端返回的数据。 服务端 创建监听套接字绑定到指定IP和端口。 等待数据通过 recvfrom() 函数接收数据。 处理请求解析数据内容并执行相应操作。 返回响应将结果数据发送回客户端。
UDP使用场景
UDP适用于以下需要高效传输但容忍数据丢失的场景
实时通信 视频通话、语音通话如VoIP。 在线游戏 游戏中快速同步状态。 流媒体传输 实时视频、音频传输。 广播/组播 数据包同时发送给多个主机如局域网中发现服务。 轻量级请求/响应 DNS查询、简单的远程控制。
UDP socket C代码示例
服务端接收数据示例bindrecvfrom 阻塞式接收信息
使用场景 简单服务端适用于单个套接字的接收
#include iostream
#include arpa/inet.h
#include sys/socket.h
#include cstringint main() {int sock_fd socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP套接字if (sock_fd 0) {perror(Socket creation failed);return -1;}struct sockaddr_in server_addr;memset(server_addr, 0, sizeof(server_addr));server_addr.sin_family AF_INET;server_addr.sin_port htons(8080); // 监听端口server_addr.sin_addr.s_addr INADDR_ANY; // 监听所有网络接口if (bind(sock_fd, (struct sockaddr*)server_addr, sizeof(server_addr)) 0) {perror(Bind failed);close(sock_fd);return -1;}char buffer[1024];struct sockaddr_in client_addr;socklen_t addr_len sizeof(client_addr);// 会阻塞等待 直到 接收信息int bytes_received recvfrom(sock_fd, buffer, sizeof(buffer), 0, (struct sockaddr*)client_addr, addr_len); // 接收数据if (bytes_received 0) {buffer[bytes_received] \0;std::cout Received message: buffer std::endl;}close(sock_fd);return 0;
}
bind 绑定-监听 函数 功能 bind 函数用于将套接字绑定到特定的IP地址和端口号通常用于服务端监听套接字。 服务器先运行监听特定的IP地址和端口号然后客户端再 函数声明 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);参数说明
sockfd 套接字描述符由 socket 函数返回。 addr 指向 sockaddr 结构体表示要绑定的地址和端口。 通常使用 sockaddr_in需强制转换为 sockaddr。 addrlen addr 的长度使用 sizeof(sockaddr_in)。
返回值 成功返回 0。 失败返回 -1并设置 errno。
示例
struct sockaddr_in server_addr;
server_addr.sin_family AF_INET;
server_addr.sin_port htons(8080); // 绑定端口号
server_addr.sin_addr.s_addr INADDR_ANY; // 绑定到所有可用IP地址if (bind(sock_fd, (struct sockaddr*)server_addr, sizeof(server_addr)) 0) {perror(Bind failed);close(sock_fd);
}为什么一般都是监听所有网络接口呢
server_addr.sin_addr.s_addr INADDR_ANY; // 绑定到所有可用IP地址这行代码中的 INADDR_ANY 是一个常用的常量它代表了一个特殊的 IP 地址即 0.0.0.0。当你将它设置为服务器套接字的地址时表示该服务器将 监听所有网络接口。 理解什么是网络接口 网络接口指计算机或设备上 每一个可以用于发送或接收数据的网络连接通道。 可以先理解为网卡但是网络接口还包括一些虚拟网卡、本地回环接口127.0.0.1、甚至 VPN接口等总的就是软硬 网络通道。 服务器为什么一般监听所有网络接口 因为理论上我们希望只要是服务器这个端口号接收的不管是哪一个网络接口都交给服务器应用程序处理除非我们就只想让服务器处理从某个网络接口 接收的数据才设置某一个网络接口的ip地址。例如 只想让服务器接受本地同一台机器上的应用程序发出的数据server_addr.sin_addr.s_addr inet_addr(127.0.0.1);为什么需要用inet_addr进行转换
因为实际是采用网络字节序进行传输的而用字符串形式十进制格式如 “192.168.1.1”只是为了人类方便阅读所以需要转为网络字节序。 inet_addr作用 用于将一个点分十进制表示的 IPv4 地址例如 “192.168.1.1”转换为网络字节序的二进制格式。 inet_addr 将一个 IPv4 地址的点分十进制字符串如 “192.168.1.1”转换为网络字节序的 32 位整数。例如 “192.168.1.1” 在十进制中是192 * 256^3 168 * 256^2 1 * 256^1 1 * 256^0对应的二进制表示是11000000 10101000 00000001 00000001 值得注意的是inet_addr 已经不推荐使用特别是在现代网络编程中因为它对无效地址的处理可能不够清晰比如返回 -1 会被误认为是有效的地址。推荐使用 inet_pton 函数来替代它更加健壮和安全。inet_pton 允许支持不同的地址族IPv4 和 IPv6并且不会出现类似 inet_addr 那样的错误返回值。
socket函数 作用 用于创建套接字socket套接字是网络通信的基础用于在客户端和服务端之间建立通信。确定协议族IPv4还是、TCP还是UDP 函数声明 int socket(int domain, int type, int protocol);参数说明
domain指定通信的协议族地址类型。
AF_INETIPv4。AF_INET6IPv6。AF_UNIX本地通信不使用网络。
type指定套接字的类型。
SOCK_STREAMTCP面向连接保证数据可靠性。SOCK_DGRAMUDP无连接适合快速传输。
protocol通常指定为 0表示使用默认协议。
如果 type 是 SOCK_DGRAM默认使用 UDP 协议。如果 type 是 SOCK_STREAM默认使用 TCP 协议。
返回值 成功返回套接字描述符非负整数。 失败返回 -1并设置 errno。
示例
int sock_fd socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd 0) {perror(Socket creation failed);
}sockaddr_in结构体 功能 用于表示 IPv4 地址和端口信息通常在网络通信中用于绑定或指定目标地址。 定义
struct sockaddr_in {short sin_family; // 地址族必须为 AF_INETunsigned short sin_port; // 端口号网络字节序需要使用 htons() 转换struct in_addr sin_addr; // IPv4 地址char sin_zero[8]; // 填充字节保持与 struct sockaddr 的大小一致不使用置 0
};字段说明
sin_family 必须设置为 AF_INETIPv4协议。 sin_port 16位端口号必须用 htons() 将主机字节序转换为网络字节序。 sin_addr 一个 struct in_addr 结构体表示IPv4地址。 可以用 inet_addr() 或 inet_aton() 转换字符串形式的IP地址。也可以设置为 INADDR_ANY表示绑定到本地所有可用IP。 sin_zero 填充字段不使用应设置为 0。
示例
struct sockaddr_in server_addr;
server_addr.sin_family AF_INET; // IPv4
server_addr.sin_port htons(8080); // 端口号转换为网络字节序
server_addr.sin_addr.s_addr inet_addr(192.168.1.1); // 目标IP地址
memset(server_addr.sin_zero, 0, sizeof(server_addr.sin_zero)); // 填充为0recvfrom 函数
作用一个用于从套接字接收数据的函数。函数声明
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);sockfd要读取数据的套接字文件描述符。buf指向接收数据的缓冲区。len缓冲区的大小。如果接收的数据超过该大小数据会被截断。flags设置标志通常为 0。 控制接收行为的标志。常用的标志包括 MSG_PEEK查看数据但不从队列中移除数据。MSG_WAITALL接收指定大小的完整数据直到所有数据都接收到才返回。MSG_DONTWAIT非阻塞操作如果没有数据可接收则立即返回。MSG_TRUNC如果接收的消息太大超过缓冲区的大小将丢弃多余部分并返回 EMSGSIZE 错误。 src_addr接收数据源的地址通常可以为 NULL如果不需要知道源地址。 创建一个指针用来接收数据源的地址 addrlen地址长度如果 src_addr 不是NULL它将被修改为实际的地址长度。
函数返回值:
成功时返回接收到的字节数。如果没有数据到达且没有设置非阻塞标志则会阻塞直到有数据可读如果设置了 MSG_DONTWAIT 或套接字为非阻塞模式它将立即返回 0 表示没有数据。失败时返回 -1并设置 errno 以指示错误。常见错误包括 EAGAIN 或 EWOULDBLOCK非阻塞模式下没有数据可接收。EBADFsockfd 不是有效的套接字。ECONNREFUSED目标主机拒绝连接仅在某些类型的套接字中出现。EINVAL无效的地址长度或参数。
客户端发送数据示例
#include iostream
#include arpa/inet.h
#include sys/socket.h
#include cstringint main() {int sock_fd socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP套接字if (sock_fd 0) {perror(Socket creation failed);return -1;}struct sockaddr_in server_addr;memset(server_addr, 0, sizeof(server_addr));server_addr.sin_family AF_INET;server_addr.sin_port htons(8080); // 目标端口号server_addr.sin_addr.s_addr inet_addr(192.168.1.1); // 目标IP地址const char* message Hello, UDP!;sendto(sock_fd, message, strlen(message), 0, (struct sockaddr*)server_addr, sizeof(server_addr)); // 发送数据close(sock_fd);return 0;
}sendto 发送 函数 功能 用于通过UDP套接字发送数据报到指定地址和端口 函数声明
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
参数说明
sockfd 套接字描述符由 socket 函数返回。 buf 指向要发送的数据的缓冲区。 len 要发送的数据长度字节数。 flags 传输标志通常设置为 0。 dest_addr 指向一个 sockaddr 结构体表示目标地址。 通常传入 sockaddr_in需要通过强制类型转换为 sockaddr。 addrlen dest_addr 的长度使用 sizeof(sockaddr_in)。 返回值 成功返回实际发送的字节数。 失败返回 -1并设置 errno。
示例
const char *message Hello, UDP!;
struct sockaddr_in server_addr;
server_addr.sin_family AF_INET;
server_addr.sin_port htons(8080);
server_addr.sin_addr.s_addr inet_addr(192.168.1.1);sendto(sock_fd, message, strlen(message), 0, (struct sockaddr*)server_addr, sizeof(server_addr));