5 Linux 网络编程基础 API

5 Linux 网络编程基础 API

主机字节序和网络字节序

  • 主机(小端)字节序:0x0201
  • 网络(大端)字节序:0x0102,利于人看
#include <netinet/in.h>
unsigned long int htonl(unsigned long int hostlong);
unsigned short int htonl(unsigned long int hostshort);
unsigned long int ntohl(unsigned long int hostlong);
unsigned short int ntohl(unsigned long int hostshort);

通用 socket 地址

#include <bits/socket.h>
// socket 地址结构体
struct sockaddr
{sa_family_t sa_family; // 地址族类型 ≈ 协议族类型char sa_data[14];
};// 新的通用 socket 结构体
struct sockaddr_storage
{sa_family_t sa_family;unsigned long int __ss_align;char __ss_padding[128 - sizeof(__ss_align)];
};

专用 socket 地址

#include <bits/socket.h>
// UNIX 本地协议族
struct sockaddr_un
{sa_family_t sin_family; // AF_UNIX == PF_UNIXchar sun_path[108];     // 文件路径名
};// IPv4
struct sockaddr_in
{sa_family_t sin_family;  // AF_INET == PF_INETu_int16_t sin_port;      // 网络字节序struct in_addr sin_addr; // Ipv4 结构体地址
};
struct in_addr
{u_int32_t s_addr; // 网络字节序
};

IP 地址转换函数

// IPv4
#include <arpa/inet.h>
in_addr_t inet_addr(const char* strptr); // INADDR_NONE
int inet_aton(const char* cp, struct in_addr* inp);// 函数内部有一个静态变量存储转化结果,返回值指向该静态内存
char* inet_ntoa(struct in_addr in);

创建 socket

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
  • domain:底层协议族,PF_UNIX、PF_INET、PF_INET6
  • type:服务类型,
    • SOCK_STREAM ==> tcp
    • SOCK_UGRAM ==> UDP
    • SOCK_NONBLOCK 新创建的 socket 设为非阻塞的
    • SOCK_CLOEXEC 用 fork 调用创建子进程时在子进程中关闭该 socket
  • protocol:0
  • return:
    • 成功:socket 文件描述符
    • 失败:-1,errno

命名 socket

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
  • return:
    • 成功:0
    • 失败:-1,errno
      • EACCES:被绑定的地址是受保护的地址,仅超级用户能够访问,比如普通用户将 socket 绑定到知名端口
      • EADDRINUSE:被绑定的地址正在使用

监听 socket

#include <sys/socket.h>
int listen(int sockfd, int backlog);
  • backlog:提示内核监听队列的最大长度,完全处理连接状态的 socket 上线
    处于半连接状态的 socket 的上线由 /proc/sys/net/ipv4/tcp_max_syn_backlog 内核参数定义
  • return:
    • 成功:0
    • 失败:-1,errno

监听队列的长度如果超过 backlog,服务器将不受理新的客户端连接,客户端也将收到 ECONNEREFUSED 错误

接受连接

  • 监听 socket:执行过 listen 调用、处于 LISTEN 状态的 socket
  • 连接 socket:处于 ESTABLISHED 状态的 socket
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
  • accept 只是从监听队列中取出连接,而不论连接处于何种状态,更不关心网络状况的变化
  • return:
    • 失败:-1,errno

发起连接

  • server 通过 listen 调用来被动接受连接
  • client 通过 connect 调用来主动与 server 建立连接
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
  • return:
    • 失败:-1,errno
      • ECONNREUFUSED:目标端口不存在,拒绝被连接
      • ETIMEDOUT:连接超时

关闭连接

#include <unistd.h>
int close(int fd);
  • close 只有将引用计数减为 0 时,才真正关闭连接
#include <sys/socket.h>
int shutdown(int sockfd, int howto);
  • 可立即终止连接(无需计数变为 0
  • howto:
    • SHUT_RD:关闭读,丢弃接收缓冲区数据
    • SHUT_WR:关闭写,发送缓冲区的数据会在真正关闭写之前发送出去,半关闭状态
    • SHUT_RDWR:

TCP 数据读写

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recv(int sockfd, void* buf, size_t len, int flags);
  • return:
    • 0:通信对方关闭连接
    • -1:errno
ssize_t send(int sockfd, const void* buf, size_t len, int flags);
  • flags:通常 0,只对当前调用生效
flags含义sendrecv
MSG_CONFIRM指示数据链路层协议持续监听对方的回应,直到得到答复,只适用于 SOCK_DGRAM 和 SOCK_RAW 类型的 socketYN
MSG_DONTROUTE不查看路由表,直接将数据发送给本地局域网络内的主机,发送者知道目标主机就在本地网络上YN
MSG_DONTWAIT对 socket 的此次操作将是非阻塞的YY
MSG_MORE告诉内核应用程序还有更多数据要发送,内核将超时等待新数据写入 TCP 发送缓冲区后一并发送,可防止 TCP 发送过多小报文段,提高传输效率YN
MSG_WAITALL读操作仅在读取到指定数量的字节后才返回NY
MSG_PEEK窥探读缓存中的数据,此次读操作不会导致这些数据被清除NY
MSG_OOB发送或接受紧急数据YY
MSG_NOSIGNAL往读端关闭的管道或者 socket 连接中写数据时不引发 SIGPIPE 信号YN

只有最后一个字符被当成正真的带外数据接收,服务器对正常数据的接收将被带外数据截断

UDP 数据读写

#include <sys/types.h>
#include <sys/socket.h>
sszie_t recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, struct sockaddr* dest_addr, socklen_t addrlen);

这两个函数也可用于面向连接的 socket 的数据读写,只需要把最后两个参数设置为 NULL 以忽略发送端、接收端的 socket 地址,已经建立了连接,双方知道对方地址

通用数据读写函数

#include <sys/socket.h>
ssize_t recvmsg(int sockfd, struct msghdr* msg, int flags);
ssize_t sendmsg(int sockfd, struct msghdr* msg, int flags);struct msghdr
{void* msg_name; // socket 地址socklen_t msg_namelen;struct iovec* msg_iov; // 分散的内存块int msg_iovlen; // 分散内存块数量void* msg_control; // 指向辅助数据的起始位置socklen_t msg_controllen;int msg_flags; // 赋值函数中的 flags 参数,并在调用过程中更新
};struct iovec
{void* iov_base; // 内存起始地址size_t iov_len; // 这块内存长度 
};
  • msg_name:指定通信对方的 socket 地址,TCP 中为 NULL
  • 分散读:对于 recvmsg,数据将被读取并存放在 msg_iovlen 块分散的内存中,这些内存的位置和长度由 msg_iov 指向的数组决定
  • 集中写:对于 sendmsg,msg_iovlen 块分散内存中的数据将被一并发送
  • msg_flags:无需设定,会复制 recvmsg、sendmsg 的 flags 参数的内容以影响数据读写过程。recvmsg 还会在调用结束前,将某些更新后的标志设置到 msg_flags 中

带外标记
内核通知应用程序带外数据到达方式:

  • I/O 复用产生的异常事件
  • SIGURG 信号
#include <sys/socket.h>
int sockatmark(int sockfd);
  • 判断 sockfd 是否处于带外标记,即下一个被读取到的数据是否是带外数据

    • SO_LINGER:控制 close 系统调用关闭 TCP 连接时的行为
  • 建议 sock 在 listen 和 accept 之前设置选项信息

网络信息 API

#include <netdb.h>
// 获取主机的完整信息
/* 先在本地 /etc/hosts 配置文件中查找主机,再去 DNS 服务器 */
struct hostent* gethostbyname(const char* name);/** @param len 指定 addr 所指 IP 地址长度* @param type 指定 addr 所指 IP 地址类型*/
struct hostent* gethostbyaddr(const void* addr, size_t len, int type);struct hostent
{char* h_name; // 主机名char** h_aliases; // 主机别名int h_addrtype; // 地址类型int h_length; // 地址长度char** h_addr_list; // 网络字节序列出主机 IP 地址列表
};// 获取服务的完整信息,通过读取 /etc/services 文件获取服务信息
/** @param proto 服务类型*              tcp 获取流服务*              udp 获取数据报服务*              NULL 获取所有类型服务*/
struct servent* getservbyname(const char* name, const char* proto);
struct servent* getservbyport(int port, const char* proto);struct servent
{char* s_name; // 服务名称char** s_aliases; // 服务别名列表int s_port; // 端口号char* s_proto; // 服务类型 tcp or udp
};/** 根据主机名获得 IP 地址(`gethostbyname`)* 根据服务名获得 port(`getservbyname`)* 是否可冲入取决于内部调用的方法* */
int getaddrinfo(const char* hostname, const char* service, const struct addrinfo* hints, struct addrinfo** result);struct addrinfo
{int ai_flags;int ai_family;int ai_socktype;int ai_protocol;socklen_t ai_addrlen;char* ai_canonname;struct sockaddr* ai_addr;struct addrinfo* ai_next;
};void freeaddrinfo(struct addrinfo* res);int getnameinfo(const struct sockaddr* sockaddr, socklen_t addrlen, char* host, socklen_t hostlen, char* serv, socklen_t servlen, int flags);/* 将 getaddrinfo 和 getnameinfo 返回的错误码转换为字符串形式 */
const char* gai_strerror(int error);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/891707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于PyQt5的UI界面开发——图像与视频的加载与显示

介绍 这里我们的主要目标是实现一个基于PyQt5和OpenCV的图像浏览和视频播放应用。用户可以选择本地的图像或视频文件夹&#xff0c;进行图像自动播放和图像切换以及视频播放和调用摄像头等操作&#xff0c;并且支持图像保存功能。项目的核心设计包括文件路径选择、图像或视频的…

云手机+Facebook:让科技与娱乐完美结合

移动互联网时代&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;早已成为企业、品牌和组织竞相角逐的营销阵地。而云手机的出现&#xff0c;则为Facebook营销注入了新的活力&#xff0c;其独特的优势让营销活动更加高效、精准且灵活。本文将深入探讨云手机在Fa…

全新免押租赁系统打造便捷安全的租赁体验

内容概要 全新免押租赁系统的推出&#xff0c;标志着租赁行业的一次重大变革。这个系统的最大特点就是“免押金”&#xff0c;大大减轻了用户在租赁过程中的经济负担。从此&#xff0c;不再需要为一部手机或其他商品支付高昂的押金&#xff0c;用户只需通过简单的信用评估&…

postman在软件测试中的应用

postman工具概述 Postman 是一款功能强大的 API 开发和测试工具&#xff0c;在软件开发和测试领域应用广泛。开发阶段&#xff0c;可以通过工具进行mock数据测试&#xff0c;方便开发&#xff0c;联调&#xff1b;测试阶段&#xff0c;可以通过不同环境&#xff0c;不同数据进…

电子电气架构 --- 安全相关内容汇总

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

探索Wiki:开源知识管理平台及其私有化部署

在如今的信息时代&#xff0c;企业和团队的知识管理变得愈发重要。如何有效地存储、整理、共享和协作&#xff0c;是提高团队效率和创新能力的关键因素之一。今天&#xff0c;我要为大家介绍一款非常有用的github上开源知识管理工具——Wiki&#xff0c;并分享它的私有化部署方…

一份完整的软件测试报告如何编写?

在软件开发的过程中&#xff0c;测试是必不可少的环节。然而&#xff0c;测试报告往往是最被忽视的部分。你是否也曾在忙碌的测试工作后&#xff0c;面对一份模糊不清的测试报告感到头疼&#xff1f;一份清晰、完整且结构合理的测试报告&#xff0c;能够帮助团队快速了解软件的…

OpenEuler22.03 LTS SP3 系统优化

OpenEuler22.03 LTS SP3 系统优化 1、关闭selinux setenforce 0 sed -i "s#SELINUXenforcing#SELINUXdisabled#g" /etc/selinux/config 2、禁用swap swapoff -a sed -ri s/.*swap.*/#&/ /etc/fstab 3、公有云机器&#xff0c;必须安全加固 &#xff08;1&…

logback之自定义过滤器

logback有两种过滤器&#xff0c;一种是context中的过滤器叫TurboFilter&#xff0c;是一个全局的过滤器&#xff0c;会影响所有的日志记录。另一种是Appender中的过滤器&#xff0c;只对所在的append有效。两者大同小异&#xff0c;这里我们以Appender的过滤器为例。 &#x…

HackMyVM-Airbind靶机的测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、Getshell 3、提权 使用ipv6绕过iptables 四、结论 一、测试环境 1、系统环境 渗透机&#xff1a;kali2021.1(192.168.101.127) 靶 机&#xff1a;debian(192.168.101.11…

前端,npm install安装依赖卡在sill idealTree buildDeps(设置淘宝依赖)

输入npm i后&#xff0c;一直卡在sill idealTree buildDeps&#xff0c;一动不动 cnpm可以安装成功&#xff0c;但使用cnpm不会生成package-lock.json文件 设置淘宝依赖&#xff0c;依然卡住&#xff0c;挂梯子也不行 解决方法&#xff1a; // 取消ssl验证 set strict-ssl …

FPGA、STM32、ESP32、RP2040等5大板卡,结合AI,更突出模拟+数字+控制+算法

板卡选择困难症了&#xff1f;如果你也想玩FPGA、STM32、ESP32、RP2040相关的板卡&#xff0c;不如看看以下几款板卡&#xff0c;如果正巧碰上能实现你想要做的项目呢~ 01 小脚丫FPGA STEP BaseBoard V4.0套件 STEP BaseBoard V4.0是第4代小脚丫FPGA扩展底板&#xff08;点击了…

go项目zero框架中表字段日期设置的几种格式对比与实践

在 GoZero 框架中&#xff0c;日期字段的格式通常取决于你的应用场景以及所使用的数据库类型。在 GoZero 中&#xff0c;日期字段的设置方式一般有两种&#xff1a;通过 time.Time 类型和通过字符串&#xff08;例如 string 或 int64&#xff09;。每种方式有其适用的场景和优缺…

UE5动画蓝图

动画蓝图&#xff0c;混合空间&#xff0c;状态机&#xff0c;瞄准偏移&#xff0c;动画蒙太奇&#xff0c;动画混合&#xff0c;骨骼绑定&#xff0c;动画重定向&#xff0c;动画通知&#xff0c;Control Rig…… 虚幻动画模块是一个庞大的系统&#xff0c;大模块里又包含很多…

XIAO Esp32S3制作网络摄像头——1音频获取

1、功能介绍 本文主要是基于XIAO Esp32S3(Sense)做的一款网络摄像头,主要包含以下功能 1 音频获取/保存 2 视频获取/视频保存 3 行人检测/火焰检测/行人追踪(告警) 4 指定区域 5 摄像头旋转 。。。 本文主要实现第一步,音频获取,后续会陆续实现后面的功能,敬请期…

Windows安装了pnpm后无法在Vscode中使用

Windows安装了pnpm后无法在Vscode中使用 解决方法&#xff1a; 以管理员身份打开 PowerShell 并执行以下命令后输入Y回车即可。 Set-ExecutionPolicy RemoteSigned -Scope CurrentUser之后就可以正常使用了

Leffa 虚拟试衣论文笔记

Leffa: Learning Flow Fields in Attention for Controllable Person Image Generation https://github.com/xuanandsix/awesome-virtual-try-on-note/tree/main/Leffa 打开链接查看详情&#xff0c;更多虚拟试穿论文持续更新。

qt5.15.2+visual studio2022 免安装版环境配置

1.环境准备 visual studio2022qt5.15.2&#xff08;免安装版本&#xff09; 2.环境配置 2.1 打开首选项 2.2 添加Qt版本 2.3 构建套件手动添加Qt 5.15.2&#xff08;msvc2019_64&#xff09;并配置如下 3.新建项目 问题1&#xff1a;qt creator 没有欢迎界面 解决办法&#…

手写顺序流程图组件

效果图 完整代码 <template><div><div class"container" :style"{ width: ${spacingX * (colNum - 1) itemWidth * colNum}px }"><divv-for"(item, i) in recordList":key"i"class"list-box":style&…

Spring Boot自定义中文Banner

Spring Boot自定义中文Banner在线生成工具 https://www.bootschool.net/https://www.bootschool.net/1.选择喜欢的复制 2.在resources文件下新建banner文件&#xff0c;粘贴即可 <_> ::::: …