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

socket与udp

网络编程-socket&UDP网络程序

01. 基础知识

1.1 IP地址

IP地址互联网协议地址,用于标识网络中的设备。通俗来说,IP地址就像你家的门牌号,它能让网络中的数据准确找到要去的设备。比如,当你在手机上访问一个网站时,你的手机会有一个 IP地址,网站服务器也有一个IP地址,数据就是通过这两个地址在设备之间传递的。


1.1.1 IPv4
  • 32位地址(4字节),点分十进制表示(192.168.1.1)
  • 地址分类:A类(1-126)、B类(128-191)、C类(192-223)

1.1.2 IPv6
  • 128位地址,冒号分隔十六进制表示,用来解决IPv4地址枯竭问题

1.2 端口号

端口号是由16位无符号整数(0-65535),用来标识主机上的特定服务。同一主机上的不同服务通过端口号区分

  • 分类
    • 0-1023:知名端口(HTTP:80, HTTPS:443, SSH:22...
    • 1024-49151:注册端口(MySQL:3306,…)
    • 49152-65535:动态/私有端口(客户端临时使用)

在这里插入图片描述


1.3 端口号与进程PID

端口号用于标识进程,进程PID也是用于标识进程,为什么在网络中,不直接使用进程PID呢?

在这里插入图片描述

  • 进程号(PID):由系统动态分配,不同主机上大概率不同,难以基于此实现跨主机通信。
  • 端口号:网络协议的一部分,是主机通过网卡通信的必经软通道,有固定约定(如80、23、443),基于固定值建立通信更直接可靠。
  • Windows开发约定:避免使用1024以前的端口,建议使用1024-65535区间的端口号。
  • 并不是所有的进程都需要进行网络通信,如果端口号、,无疑会影响网络管理的效率PID都使用同一个解决方案,会影响网络管理效率。

在这里插入图片描述


1.4 传输层协议

  • TCP
    • 面向连接、可靠传输,字节流
    • 三次握手建立连接,四次挥手断开连接
    • 流量控制、拥塞控制
    • 适用场景:文件传输、网页浏览、邮件
    • TCP 流程socket()bind()listen()accept()(服务器);socket()connect()(客户端);之后用 send()/recv() 通信。
  • UDP
    • 无连接、不可靠传输,数据报
    • 低延迟、无拥塞控制
    • 适用场景:视频流、DNS查询、游戏实时数据
    • UDP 流程socket()bind()(可选);用 sendto()/recvfrom() 直接通信。

1.5 网络字节序

由于不同CPU架构使用不同字节序(大端/小端)。所以TCP/IP 协议规定网络中传输的数据,统一采用大端存储方案,也就是网络字节序,现在大端/小端称为主机字节序


1.5.1 字节序转换函数
#include <arpa/inet.h>// 16位转换
uint16_t htons(uint16_t hostshort);  //short常用于端口号 主机->网络
uint16_t ntohs(uint16_t netshort);   //long常用于 IP 地址 网络->主机// 32位转换
uint32_t htonl(uint32_t hostlong);
uint32_t ntohl(uint32_t netlong);

1.5.2 IP地址转换函数
// 将点分十进制 IPv4 字符串转为网络字节序整数。
in_addr_t inet_addr(const char *cp);
int inet_pton(int af, const char *src, void *dst);// 将网络字节序 IPv4 整数转为点分十进制字符串(线程不安全)。
char *inet_ntoa(struct in_addr in);
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

02. socket 套接字

socket 套接字提供了下面这一批常用接口,用于实现网络通信。


2.1 socket 常见API

2.1.1 socket()

创建一个socket描述符,用于后续网络操作。

int socket(int domain, int type, int protocol);
  • 参数:
    • domain:协议族, AF_INET(IPv4)、AF_INET6(IPv6)…
    • type:socket 类型, SOCK_STREAMSOCK_DGRAM
    • protocol:协议类型,通常为 0
  • 返回值:成功返回socket描述符即文件描述符,失败返回 -1

2.1.2 bind()

将 socket 与特定的IPport绑定(主要用于服务器)。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
  • 参数:
    • sockfdsocket() 返回的文件描述符
    • addr:指向 sockaddrsockaddr_in的指针,包含要绑定的地址信息
    • addrlenaddr 结构体的大小
  • 返回值:成功 0,失败 -1

注意: bind()接收 sockaddr* 类型,需将 sockaddr_in* 转换为 sockaddr*如:

struct sockaddr_in serv_addr;
bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

2.1.3 sendto()recvfrom()
  • sendto():向指定地址发送数据。

    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
    
    • dest_addr:目标主机的地址信息。

  • recvfrom():从指定地址接收数据。

    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
    
    • src_addr:输出参数,存储发送方的地址信息(可设为 NULL)。

2.1.4close()

关闭 socket 描述符,释放资源。

int close(int fd);

2.2 sockaddr 结构体详解

struct sockaddr {sa_family_t sa_family;  // 地址族char        sa_data[14]; // 地址数据(变长,依地址族而定)
};

socket网络通信标准隶属于POSIX通信标准,该标准的设计初衷就是为了实现 可移植性,程序可以直接在使用该标准的不同机器中运行,但有的机器使用的是网络通信,有的则是使用本地通信,socket套接字为了能同时兼顾这两种通信方式,提供了sockaddr结构体
sockaddr结构体衍生出了两个不同的结构体:sockaddr_in网络套接字、sockaddr_un域间套接字,前者用于网络通信,后者用于本地通信

  • sockaddr 是通用的地址结构体。
  • 可以根据16位地址类型,判断是网络通信,还是本地通信
  • 在进行网络通信时,需要提供IPport等网络通信必备项,本地通信只需要提供一个路径名,通过文件读写的方式进行通信(类似于命名管道)

在这里插入图片描述

socket提供的接口参数为sockaddr*,我们既可以传入&sockaddr_in进行网络通信,也可以传入&sockaddr_un进行本地通信,传参时将参数进行强制类型转换即可,这是使用 C语言实现多态的典型做法,确保该标准的通用性。


2.2.1 sockaddr _in定义

sockaddr_in 定义在 <netinet/in.h> 头文件中,其核心作用是存储 IPv4 协议的地址信息,包括IPport协议族等。在 socket 编程中,很多函数(如 bind()connect()recvfrom() 等)需要接收一个 sockaddr类型的指针作为参数,而 sockaddr_insockaddr 针对IPv4的 “具体化” 实现。


2.2.2 sockaddr _in结构体成员
struct sockaddr_in {sa_family_t    sin_family;   // 地址族(必须为 AF_INET)in_port_t      sin_port;     // 端口号(网络字节序)struct in_addr sin_addr;     // IPv4 地址(网络字节序)char           sin_zero[8];  // 填充字段,使结构体大小与 sockaddr 一致
};

2.2.3 sin_addr

struct in_addr(嵌套结构体,用于存储 IPv4 地址)。s_addr 存储 32 位 IPv4 地址。

struct in_addr {in_addr_t s_addr;  // IPv4 地址(32位整数,网络字节序)
};

注意:必须使用网络字节序。

  • 直接赋值:sin_addr.s_addr = inet_addr("192.168.1.1");inet_addr() 自动转换为网络字节序)。
  • 绑定任意地址:sin_addr.s_addr = INADDR_ANY;(表示监听本机所有网卡的IP地址)。

sockaddr_insockaddr 针对IPv4的专用版本,两者大小相同(16 字节),可通过强制类型转换互相兼容。


03. 网络程序

加载中…

http://www.dtcms.com/a/314328.html

相关文章:

  • 折叠屏网页布局挑战:响应式设计在工业平板与PC端的弹性适配策略
  • 【Mac】OrbStack:桌面端虚拟机配置与使用
  • LeetCode 140:单词拆分 II
  • 【MySQL03】:MySQL约束
  • mac 技巧
  • 零售消费行业研究系列报告
  • Java-基础-统计投票信息
  • Linux下载安装mysql,客户端(Navicat)连接Linux中的mysql
  • allegro建库--1
  • 【Redis】移动设备离线通知推送全流程实现:系统推送服务与Redis的协同应用
  • 模型学习系列之考试
  • 机器学习(8):线性回归
  • 基于落霞归雁思维框架的自动化测试实践与探索
  • OpenLayers 入门指南【五】:Map 容器
  • Unity发布Android平台实现网页打开应用并传参
  • 如何查看 iOS 电池与电耗:入门指南与实战工具推荐
  • 期权投资盈利之道书籍推荐
  • Codeforces Round 1008 (Div. 2)
  • Chrontel【CH7214C-BF】CH7214C USB Type C Logic Controller
  • 【Java线程池深入解析:从入门到精通】
  • Memcached 缓存详解及常见问题解决方案
  • 【深度学习新浪潮】近三年城市级数字孪生的研究进展一览
  • 【音视频】WebRTC 一对一通话-实现概述
  • 使用vue缓存机制 缓存整个项目的时候 静态的一些操作也变的很卡,解决办法~超快超简单~
  • 深入剖析RT-Thread串口驱动:基于STM32H750的FinSH Shell全链路Trace分析与实战解密(上)
  • Back to the Features:附录C Unconditional world model evaluations
  • 第四十一节 MATLAB GNU Octave教程
  • 第四十五章:AI模型的“灵魂契约”:GGUF权重到PyTorch结构极致适配
  • Nginx vs Spring Cloud Gateway:限流功能深度对比与实践指南
  • 政策合规性网页设计:工业数据可视化的信息安全技术规范解析