【C语言教程】【常用类库】(十五)网络编程 - <sys/socket.h> 和 <netinet/in.h>
15. 网络编程 - <sys/socket.h> 和 <netinet/in.h>
网络编程在C语言中是通过套接字来实现的,套接字提供了进程间通信的端点。C语言的网络编程涉及到创建套接字、绑定地址、监听和接收数据。以下是网络编程的关键概念和基本实现方法。
15.1. 套接字基础
15.1.1. 套接字类型与协议
套接字是网络通信的基础,它分为不同的类型和协议:
-
套接字类型:
- 流套接字(
SOCK_STREAM):基于TCP协议,提供可靠的双向字节流通信。 - 数据报套接字(
SOCK_DGRAM):基于UDP协议,无连接,面向消息,通信时不保证消息顺序和完整性。
- 流套接字(
-
协议:
- TCP(传输控制协议):提供可靠、有序的字节流服务,比如HTTP。
- UDP(用户数据报协议):提供较低效能的、不可靠的数据报服务,比如DNS查询。
15.1.2. 创建和绑定套接字:socket, bind
创建套接字并绑定到指定IP和端口是建立网络服务的基础步骤。
-
socket函数:用于创建一个新的套接字。int socket(int domain, int type, int protocol);domain:地址族,一般为AF_INET(IPv4)或AF_INET6(IPv6)。type:套接字类型,如SOCK_STREAM(TCP)或SOCK_DGRAM(UDP)。protocol:通常设为0,自动匹配。
-
bind函数:将套接字与特定IP地址和端口绑定。int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd:由socket返回的文件描述符。addr:IP地址和端口信息结构体,通常为struct sockaddr_in。addrlen:地址结构体的长度。
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>int main() {int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字 [1]struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr)); // 清零server_addr.sin_family = AF_INET; // IPv4server_addr.sin_addr.s_addr = INADDR_ANY; // 任意可用的接口server_addr.sin_port = htons(8080); // 绑定端口8080bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 绑定套接字 [2]return 0;
}
- [1]创建套接字:使用
socket函数创建TCP套接字。IPv4地址AF_INET,流套接字类型。 - [2]绑定套接字:
bind函数将创建的套接字绑定到结构体中指定的IP地址和端口上。
15.2. 客户端与服务器模型
15.2.1. TCP 服务器:listen, accept
在创建并绑定了套接字后,服务器需要监听连接和接受请求。
-
listen函数:将套接字设置为被动监听状态。int listen(int sockfd, int backlog);sockfd:套接字描述符。backlog:等待连接队列的最大长度。
-
accept函数:从连接队列中取出一个连接请求。int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd:监听中的套接字。addr:客户机的IP地址和端口信息。addrlen:用户提供的地址结构的大小。
listen(sockfd, 5); // 开始监听 [3]
struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);
int client_sockfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen); // 接受连接 [4]
- [3]监听连接:
listen将套接字置为监听状态。 - [4]接受连接:
accept从队列中取出一个连接。
15.2.2. TCP 客户端:connect
客户端需要连接到服务端的指定地址和端口。
connect函数:用于连接到服务端。int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);sockfd:套接字描述符。addr:服务端的 IP 地址和端口信息。addrlen:服务器地址信息的结构体大小。
int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 创建套接字
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr)); // 清空地址
server_addr.sin_family = AF_INET; // IPv4
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // IP 地址 [5]
server_addr.sin_port = htons(8080); // 目标端口
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); // 发起连接请求 [6]
- [5]设置地址:使用
inet_pton设置目标服务的 IP。 - [6]发起连接请求:
connect连接到指定服务器。
15.2.3. 数据传输:send, recv
一旦连接建立,服务端和客户端之间就可以通过以下函数进行数据传输。
-
send函数:用于发送数据。ssize_t send(int sockfd, const void *buf, size_t len, int flags);sockfd:套接字描述符。buf:要发送的缓冲区。len:缓冲区长度。flags:传输标志,通常设置为0。
-
recv函数:用于接收数据。ssize_t recv(int sockfd, void *buf, size_t len, int flags);用法与
send类似。
char buffer[1024];
send(client_sockfd, "Hello, World!", 13, 0); // 发送信息 [7]
recv(client_sockfd, buffer, sizeof(buffer), 0); // 接收信息 [8]
- [7]发送信息:使用
send传输数据。 - [8]接收信息:使用
recv接收数据。
15.3. 高级套接字编程
15.3.1. 多路复用:select, poll
多路复用允许程序在一个线程中监视多个文件描述符上的事件。
-
select函数:用于监视多个文件描述符。int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); -
poll函数:与select相似,使用pollfd结构体数组。int poll(struct pollfd *fds, nfds_t nfds, int timeout);
15.3.2. UDP 套接字编程
UDP 套接字不需要连接,可以直接使用 sendto 和 recvfrom。
-
sendto函数:用于发送UDP数据包。ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen); -
recvfrom函数:用于接收UDP数据包。ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
char udp_buffer[1024];
struct sockaddr_in dest_addr;
memset(&dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.1.1", &dest_addr.sin_addr);
dest_addr.sin_port = htons(9090);
sendto(sockfd, "UDP message", 11, 0, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); // 发送UDP [9]
recvfrom(sockfd, udp_buffer, sizeof(udp_buffer), 0, NULL, NULL); // 接收UDP [10]
- [9]发送UDP: 使用
sendto发出数据。 - [10]接收UDP: 使用
recvfrom接收UDP数据。
通过这些概念和代码示例,你可以开始进行C语言的网络编程,创建基本的网络应用程序。无论是客户端还是服务器端处理,正确使用这些网络编程API是至关重要的。
相关文章:
【C语言教程】【常用类库】(十五)网络编程 - <sys/socket.h> 和 <netinet/in.h>
15. 网络编程 - <sys/socket.h> 和 <netinet/in.h> 网络编程在C语言中是通过套接字来实现的,套接字提供了进程间通信的端点。C语言的网络编程涉及到创建套接字、绑定地址、监听和接收数据。以下是网络编程的关键概念和基本实现方法。 15.1. 套接字基础…...
正点原子讲解SPI学习,驱动编程NOR FLASH实战
配置SPI传输速度时,需要先失能SPI,__HAL_SPI_DISABLE,然后操作SPI_CR1中的波特率设置位,再使能SPI, NM25Q128驱动步骤 myspi.c #include "./BSP/MYSPI/myspi.h"SPI_HandleTypeDef g_spi1_handler; /* SPI句柄 */void spi1_init(void) {g_spi…...
低代码开发助力中小企业数字化转型难度持续降低
随着信息技术的飞速发展,数字化转型已成为企业持续发展的关键驱动力。对于中小企业而言,数字化转型不仅意味着提升效率、降低成本,更是实现业务模式创新和市场竞争力提升的重要途径。然而,传统软件开发模式的高成本、长周期和复杂…...
【Linux】:线程控制
朋友们、伙计们,我们又见面了,本期来给大家带来线程控制相关代码和知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏:C语言:从入门到精通 数…...
大数据-174 Elasticsearch Query DSL - 全文检索 full-text query 匹配、短语、多字段 详细操作
点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...
Spring Boot视频网站:构建可扩展的视频服务平台
6系统测试 为了保证所开发出来的系统质量过关,让所开发出来的系统具备可靠性并能够投入运行使用,这就需要进行系统开发的最后一个关键步骤,那就是系统测试。可以说系统测试就是对系统开发前面的步骤,比如系统分析与设计等进行复查…...
护眼台灯横评:书客、柏曼、明基哪款使用体验好,又能护眼?
如果你使用过护眼台灯,就太能理解为什么护眼台灯会诞生了。护眼台灯确实有一定的护眼作用,光线柔和不刺眼,许多护眼台灯还有智能调光、定时休息等人性化功能。在当今这个数字化时代,长时间面对电脑屏幕或埋头于书本已成为许多人的…...
RDMA笔记
目录 1. RDMA简介1.1. 比较Socket与RDMA的通信1.2. RDMA优势1.3. RDMA 2. RDMA基本元素2.1. QPSQ, SQE & RQ, RQEQPNQPC 2.2. CQ2.3. MR2.4. PD 3. RDMA基本操作3.1. Send & Receive3.2. RDMA Write3.3. RDMA Read 阅读RDMA相关资料,从硬件开发角度对RDMA作…...
Collection 单列集合 List Set
集合概念 集合是一种特殊类 ,这些类可以存储任意类对象,并且长度可变, 这些集合类都位于java.util中,使用的话必须导包 按照存储结构可以分为两大类 单列集合 Collection 双列集合 Map 两种 区别如下 Collection 单列集合类的根接口,用于存储一系列符合某种规则的元素,它有两…...
LabVIEW提高开发效率技巧----跨平台开发
在如今的多平台环境下,开发者常常面临不同操作系统的需求,如Windows、Linux和RT(实时)系统等。而LabVIEW作为一种强大的开发工具,提供了支持跨平台开发的能力,但要使其无缝迁移,开发者需要掌握一…...
创建uniCloud新项目并且是新服务空间,运行会报Error: Invalid uni-id config file错误
问题说明 新创建的服务空间,新起的项目,运行查询数据库就会报错,Uncaught (in promise) Error: Invalid uni-id config file,我记得在原来创建项目的时候,是不需要进行配置的,最近创建新项目出现了这个错误…...
七、IPD 方法论框架(IPD的组织架构)
IPD的组织架构 在IPD(集成产品开发)方法论中,组织架构是确保跨职能团队高效协作、快速响应市场需求的关键要素之一。IPD的组织架构通常打破传统的职能部门隔离,倡导跨职能团队和矩阵式管理模式,使各职能部门在项目开发中紧密合作,从而提高开发效率,降低沟通成本。 IPD…...
iPad mini 7惨遭暗砍一刀
大屏是工作,小屏才是生活。 iPad mini系列,一直被誉为最适合普罗大众的平板。热爱学习、工作的卷王不多,沉迷游戏、追剧的俗人不少。 对娱乐场景而言,便携性是核心属性。iPad mini不大不小,只有两台手机的大小&#x…...
【计算机网络 - 基础问题】每日 3 题(三十六)
✍个人博客:https://blog.csdn.net/Newin2020?typeblog 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞…...
Docker镜像
Docker是一个开源的容器化平台,它可以帮助开发人员打包应用程序及其依赖项为轻量级、可移植的容器,以实现快速部署和可扩展性。下面是关于Docker的一些基本概念和优势: 容器:Docker使用容器来封装应用程序和其所有依赖项ÿ…...
Golang | Leetcode Golang题解之第478题在圆内随机生成点
题目: 题解: type Solution struct {radius, xCenter, yCenter float64 }func Constructor(radius, xCenter, yCenter float64) Solution {return Solution{radius, xCenter, yCenter} }func (s *Solution) RandPoint() []float64 {r : math.Sqrt(rand.…...
菜鸟笔记006 截图识别文字插件 textOCR
随手可得的截图识别文字插件 textOCR,识别出来的文字可直接输入到illustrator的当前文档中: 执行条件 1、需截图软件支持,推荐笔记截图工具 2、截好图片直接拖入面板即可完成识别 ****后期可完成实现在illustrator选择图片对象完成文字识别。…...
MySQL【知识改变命运】07
MySQL 1:Group by 分组查询1.1:语法:1.2:练习 2:having⼦句3回顾:3:内置函数3.1 :⽇期函数 1:Group by 分组查询 可以根据某列,进行分组查询,比如学校里面的…...
Matlab自学笔记三十八:日期时间序列的创建方法
1.概念 时间序列是指,某一时间段的时间,也就是说,一组日期时间数据组成的序列,例如,1.1~1.10,1点~5点等,在Matlab中,使用向量表示这种时间序列,例如[2025.1.1 2025.1.2 …...
fiber的原理
React Fiber 的主要原理包括动态优先级、可中断的工作、增量渲染和协作式多任务 React Fiber 是 React 16 引入的一种新的协调(reconciliation)引擎,它旨在提高 React 应用的性能和响应性。Fiber 的核心原理主要包括以下几个方面:…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
