Socket编程UDP

网络字节序

我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于

文件中的偏移地址也有大端小端之分, 网络数据流同样有大端小端之分. 那么如何定义网络数据流的地

址呢?

  • 网络数据流的地址这样规定:先发出的数据是低地址,后发出的数据是高地址.

为使网络程序具有可移植性,使同样的C代码在大端和小端计算机上编译后都能正常运行,可以调用以下

库函数做网络字节序和主机字节序的转换。

htons/htonl/ntohl/ntohs

c 复制代码
#include<arpa/inet.h>
unit32_t htonl(unit32_t hostlong);
  • 参数:hostlong:主机字节序的32位无符号整数
  • 返回值:网络字节序的32位整数
c 复制代码
#include<arpa/inet.h>
unit16_t htons(unit16_t hostlong);
  • 参数:hostshort:主机字节序的16位无符号整数
  • 返回值:网络字节序的16位整数
c 复制代码
#include<arpa/inet.h>
uint16_t ntohs(uint16_t netshort);
  • 参数: netshort: 网络字节序的16位整数
  • 返回值:网络字节序的16位整数
c 复制代码
#include<arpa/inet.h>
uint32_t ntohl(uint32_t netlong);
  • 参数:netlong: 传入网络字节序的32位整数
  • 返回值:网络字节序的16位整数

函数 功能 含义 适用场景
htons 主机序 → 网络序,16 位 host to network short 端口号 (uint16_t)
htonl 主机序 → 网络序,32 位 host to network long IPv4 整型地址 (uint32_t)
ntohs 网络序 → 主机序,16 位 network to host short 从 sockaddr 取出端口解析
ntohl 网络序 → 主机序,32 位 network to host long 从 sockaddr 取出 ip 整型解析

记忆规则

  1. h 开头:h(ost) → n(etwork) 主机转网络,用于填sockaddr结构体,准备发包
  2. n 开头:n(etwork) → h(ost) 网络转主机,用于从sockaddr取出数据,程序内打印/计算
  3. s = short 16位 → 端口
  4. l = long 32位 → IPv4地址

使用示例

c 复制代码
#include <stdio.h>
#include <arpa/inet.h>

int main() {
    // 端口号转换(16位)
    uint16_t host_port = 8080;
    uint16_t net_port = htons(host_port);
    printf("Host port: %u -> Network port: %u\n", host_port, net_port);
    
    // IP地址转换(32位)
    uint32_t host_ip = 0xC0A80101;  // 192.168.1.1
    uint32_t net_ip = htonl(host_ip);
    printf("Host IP: 0x%08X -> Network IP: 0x%08X\n", host_ip, net_ip);
    
    // 从网络序转回主机序
    uint16_t back_port = ntohs(net_port);
    uint32_t back_ip = ntohl(net_ip);
    
    return 0;
}

socket

c 复制代码
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);
参数 说明 常用值
domain 协议族/地址族 AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNIX(本地)
type 套接字类型 SOCK_STREAM(TCP)、SOCK_DGRAM(UDP)、SOCK_RAW(原始)
protocol 协议(通常为 0) 0(自动选择)、IPPROTO_TCP、IPPROTO_UDP
  • domain:和一个结构体有关------struct sockaddr,本地选择AF_UNIX网络通信选AF_INET

sockaddr结构

socket API是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要讲的UNIX

Domain Socket. 然而, 各种网络协议的地址格式并不相同.

  • IPv4、IPv6地址类型分别定义为常数AF_INET、AF_INET6. 这样,只要取得某种sockaddr结构体的
    首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的
    内容.
  • socket API可以都用struct sockaddr *类型表示, 在使用的时候需要强制转化成sockaddr_in; 这样
    的好处是程序的通用性, 可以接收IPv4, IPv6, 以及UNIX Domain Socket各种类型的sockaddr结构
    体指针做为参数;

sockaddr结构

sockaddr_in结构

虽然socket api的接口是sockaddr, 但是我们真正在基于IPv4编程时, 使用的数据结构是sockaddr_in;

这个结构里主要有三部分信息: 地址类型, 端口号, IP地址.

in_addr结构

in_addr用来表示一个IPv4的IP地址. 其实就是一个32位的整数;

bind

bind() 的作用是 给套接字绑定一个本地地址(IP + 端口),即告诉操作系统这个套接字在哪个地址上监听或发送数据

c 复制代码
#include <sys/socket.h>

int bind(int socket, const struct sockaddr *address, socklen_t address_len);
参数 类型 说明
socket int 由 socket() 函数返回的文件描述符
address const struct sockaddr * 指向套接字地址结构的指针(需强制转换)
address_len socklen_t address 所指结构的大小(字节数)

bzero() 函数详解

bzero() 将内存区域 s 的前 n 个字节全部设置为零(\0)。

c 复制代码
#include <strings.h>

void bzero(void *s, size_t n);
参数 类型 说明
s void * 指向要清零的内存区域的指针
n size_t 要清零的字节数

recvfrom

recvfrom() 的主要作用是 从无连接套接字接收数据,并获取发送方的地址。

c 复制代码
#include <sys/types.h>
#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
参数 类型 说明
sockfd int 套接字文件描述符
buf void * 接收数据的缓冲区指针
len size_t 缓冲区大小(字节数)
flags int 接收标志(通常设为 0)
src_addr struct sockaddr * 输出参数:存储发送方地址信息,可为 NULL
addrlen socklen_t * 输入输出参数:传入地址结构大小,返回实际地址长度
  • sockfd:是socket接口的返回值。

sendto

sendto() 的主要作用是 通过套接字向指定目标地址发送数据 ,特别适用于 无连接的通信协议(如 UDP)。

c 复制代码
#include <sys/types.h>
#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
参数 类型 说明
sockfd int 套接字文件描述符
buf const void * 指向要发送数据的缓冲区
len size_t 要发送的字节数
flags int 发送选项标志(通常为 0)
dest_addr const struct sockaddr * 目标地址结构指针
addrlen socklen_t dest_addr 结构的大小
相关推荐
牛马也想出海15 小时前
亚马逊爬虫代理IP:IP类型选择与配置指南
开发语言·php
梦梦代码精16 小时前
基于UniApp+Vue3+ThinkPHP 8,这套知识付费系统的架构设计有点东西
java·低代码·docker·uni-app·开源·php
bitbrowser18 小时前
MXToolbox检测IP只红一个黑名单时,如何判断?
网络·网络协议·tcp/ip
lxw184491251419 小时前
PHP5、PHP7、PHP8 版本核心区别与特性
人工智能·php
AI直播技术杂谈19 小时前
直播画面突然模糊了,排查了三个小时
开发语言·php
heimeiyingwang19 小时前
【架构实战】可观测性三支柱实战:Metrics、Logging、Tracing 如何统一落地
开发语言·架构·php
智购科技自动贩卖机1 天前
自动售货机硬件主控方案选型实战:单片机、树莓派、ESP32怎么选?
人工智能·单片机·嵌入式硬件·物联网·网络协议·yolo·架构
CRMEB1 天前
商城大促活动策划全流程:从定目标到复盘四阶段
java·开发语言·人工智能·ai·开源·php
00后程序员张1 天前
SSL Pinning 抓包抓不到明文?绕过证书固定的几种方案
网络协议·计算机网络·网络安全·ios·adb·https·udp