Day37 socket、TCP、UDP
socket类型
流式套接字(SOCK_STREAM) TCP
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。
数据报套接字(SOCK_DGRAM) UDP
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。
原始套接字(SOCK_RAW)
可以对较低层次协议如IP、ICMP直接访问。
服务器:
1.创建流式套接字(socket())------------------------> 有手机
2.指定本地的网络信息(struct sockaddr_in)----------> 有号码
3.绑定套接字(bind())------------------------------>绑定电话
4.监听套接字(listen())---------------------------->待机
5.链接客户端的请求(accept())---------------------->接电话
6.接收/发送数据(recv()/send())-------------------->通话
7.关闭套接字(close())----------------------------->挂机
客户端:
1.创建流式套接字(socket())----------------------->有手机
2.指定服务器的网络信息(struct sockaddr_in)------->有对方号码
3.请求链接服务器(connect())---------------------->打电话
4.发送/接收数据(send()/recv())------------------->通话
5.关闭套接字(close())--------------------------- >挂机
函数接口
socket
int socket(int domain, int type, int protocol);
//作用:创建一个socket通信描述符
domain:指定通信的域(通信协议)AF_UNIX, AF_LOCAL 本地通信AF_INET ipv4AF_INET6 ipv6
type:指定socket的类型SOCK_STREAM:流式套接字,接下来我们的通信使用TCP协议SOCK_DGRAM:数据报套接字,接下来我们的通信使用UDP协议
protocol:填0 返回值:如果成功,返回创建的描述符,如果失败,返回-1
connect
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
作用:请求连接服务器
参数:
sockfd:上面socket接口得到的描述符
addr:相当于服务器的地址(IP+port)
addrlen:地址的长度,因为前面的地址是可变的,所以要通过参数来协定地址的长度
返回值:
0 -1
sockaddr结构体
//从bind接口的帮助文档中拿到
struct sockaddr {sa_family_t sa_family;char sa_data[14];}
上述地址结构是一个通用结构,我们在用实际协议进行通信的时候,需要转换成相应协议的结构体。
用man 7 ip来查看ipv4对应的结构体struct sockaddr_in {sa_family_t sin_family; /* 地址协议族,=socket接口第一个参数 */in_port_t sin_port; /* 指定端口,端口要用网络字节序(大端) */struct in_addr sin_addr; /* IP地址 */
};/* Internet address. */
struct in_addr {uint32_t s_addr; /* address in network byte order */
};
bind
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
作用:绑定服务器地址:IP和端口,相当于对外公开自己的IP和端口,客户端就可以连接了
addr:绑定的IP和端口结构体,注意绑定的是自己的IP和端口IP:取真实的某个网卡的地址,也可以直接写0.0.0.0
addrlen:地址的大小
listen
int listen(int sockfd, int backlog);
作用:进入监听状态,以便接收客户端的连接
sockfd:上面的服务器描述符
backlog:同时能处理的客户端的连接数量,写个5 10都可以
返回值:0 -1
accept
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
接收客户端连接,注意,这是一个阻塞接口,如果没有新的连接过来,那么会等待
sockfd:上面的服务器描述符
addr:客户端的地址(来电显示)
addrlen:客户端地址的长度,是入参,传入然后可能会被接口修改返回值:如果成功,会返回一个非负的整数,代表接收的新的连接的描述符
recv/send
//recv和send是网络的专用接口,比起read和write只是多了一个flags参数,flag一般情况下会取0,代表阻塞接受和发送
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
返回值:>0:接收的字节数<0:失败=0:代表对端退出了
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
close
int close(int fd);
关闭套接字连接
TCP

示例代码
TCP客户端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>int main(int argc, char const *argv[])
{//创建套接字int fd = socket(AF_INET, SOCK_STREAM, 0);if(fd < 0){perror("socket err");return -1;}//连接到服务器struct sockaddr_in server_addr;int len = sizeof(server_addr);//指定连接的服务器的地址(IP+port)memset(&server_addr, 0, len);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8888);server_addr.sin_addr.s_addr = inet_addr("192.168.0.109");int ret = connect(fd, (struct sockaddr *)&server_addr, len);if(ret < 0){perror("connect err");return -1;}printf("conect success\n");char buf[64] = {0};while (1){memset(buf, 0, 64);//从终端接收用户输入,发给服务器,等待服务器的数据,打印gets(buf);if(strcmp(buf, "quit") == 0){break;}send(fd, buf, 64, 0);memset(buf, 0, 64);ret = recv(fd, buf, 64, 0);if(ret > 0){printf("recv data = %s\n", buf);}else if(ret == 0){printf("peer exit\n");break;}else{perror("recv err\n");return -1;}}close(fd);return 0;
}
TCP服务器
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>int main(int argc, char const *argv[])
{//创建服务器的套接字int server_fd = socket(AF_INET, SOCK_STREAM, 0);if(server_fd < 0){perror("socket err");return -1;}//初始化服务器地址struct sockaddr_in server_addr, client_addr;int len = sizeof(server_addr);memset(&server_addr, 0, len);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8888);
#if 0 server_addr.sin_addr.s_addr = inet_addr("192.168.0.194");
#elseserver_addr.sin_addr.s_addr = INADDR_ANY;
#endif//绑定套接字的地址int ret = bind(server_fd, (struct sockaddr *)&server_addr, len);if(ret < 0){perror("bind err");return -1;}//启动监听ret = listen(server_fd, 5);if(ret < 0){perror("listen err");return -1;}//接收连接int clientfd = accept(server_fd, (struct sockaddr *)&client_addr, &len);if(clientfd < 0){perror("accept err");return -1; }//打印客户端的地址,注意端口要转成主机字节序printf("recv a new connect, ip = %s, port=%d\n",\inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));char buf[64] = {0};while (1){memset(buf, 0, 64);//一旦新的连接过来后,后续通信统统使用新的描述符len = read(clientfd, buf, 64);if(len > 0){printf("recv data = %s\n", buf);}else if(len == 0){printf("client exit\n");break;}else{perror("recv err\n");return -1;}}close(clientfd);close(server_fd);return 0;
}
UDP
TCP和UDP的异同点
相同点:
同属于传输层协议
不同点:
TCP:流式套接字,面向连接的,可靠的通信
UDP:数据报套接字,无连接的,不可靠的通信
通信流程

接口
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
作用:接收UDP对端发来的消息
sockfd:描述符
buf:接收缓冲区
len:缓冲区的长度
flags:填0,阻塞接收
src_addr:收到消息后,对端的地址存到这里(IP+PORT)
addrlen:src_addr缓冲区长度ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
作用:发送消息给UDP对端
sockfd:描述符
buf:发送缓冲区
len:发送的长度
flags:填0,阻塞发送
dest_addr:发送的目的地址(IP+PORT)
addrlen:dest_addr的长度
PS:UDP的端口和TCP的端口是独立的!!
代码示例
UDP服务器
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define KB 1024int main(int argc, char const *argv[])
{//创建服务器的套接字int server_fd = socket(AF_INET, SOCK_DGRAM, 0);if(server_fd < 0){perror("socket err");return -1;}//初始化服务器地址struct sockaddr_in server_addr, client_addr;int len = sizeof(server_addr);memset(&server_addr, 0, len);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8888);
#if 0 server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
#elseserver_addr.sin_addr.s_addr = INADDR_ANY;
#endif//绑定套接字的地址int ret = bind(server_fd, (struct sockaddr *)&server_addr, len);if(ret < 0){perror("bind err");return -1;}//接收消息,收到客户端消息,然后把客户端的消息再返回给客户端char buf[KB] = {0};struct sockaddr_in cli_addr;socklen_t addrlen = sizeof(struct sockaddr_in);while (1){memset(buf, 0, KB);//服务器一定是先接收的len = recvfrom(server_fd, buf, KB, 0,(struct sockaddr *)&cli_addr, &addrlen);if(len < 0){perror("recv err");return -1;}printf("recv from %s--%d,data=%s\n", inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port), buf);//接收成功,而且对端地址存储到了cli_addr中sendto(server_fd, buf, len, 0,(struct sockaddr *)&cli_addr, addrlen);}close(server_fd);return 0;
}
UDP客户端
#include <stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define KB 1024int main(int argc, char const *argv[])
{//创建套接字int fd = socket(AF_INET, SOCK_DGRAM, 0);if(fd < 0){perror("socket err");return -1;}//连接到服务器struct sockaddr_in server_addr;int len = sizeof(server_addr);//指定连接的服务器的地址(IP+port)memset(&server_addr, 0, len);server_addr.sin_family = AF_INET;server_addr.sin_port = htons(8888);server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");char buf[KB] = {0};socklen_t addrlen = sizeof(struct sockaddr_in);while (1){memset(buf, 0, KB);gets(buf);sendto(fd, buf, strlen(buf), 0, (struct sockaddr *)&server_addr, addrlen);memset(buf, 0, KB);len = recvfrom(fd, buf, KB, 0, NULL, NULL);printf("recv from server data = %s\n", buf);}close(fd);return 0;
}相关文章:
Day37 socket、TCP、UDP
socket类型 流式套接字(SOCK_STREAM) TCP 提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。 数据报套接字(SOCK_DGRAM) UD…...
从 Language Model 到 Chat Application:对话接口的设计与实现
作者:网隐 RTP-LLM 是阿里巴巴大模型预测团队开发的大模型推理加速引擎,作为一个高性能的大模型推理解决方案,它已被广泛应用于阿里内部。本文从对话接口的设计出发,介绍了业界常见方案,并分享了 RTP-LLM 团队在此场景…...
无人机|LQR控制算法及其无人机控制中的应用仿真
前言 LQR全称Linear Quadratic Regulator(线性二次调节器),顾名思义用于解决形如 x ˙ A x B u y C x D u \begin{aligned}\dot{x}&AxBu\\y&CxDu\end{aligned} x˙yAxBuCxDu 线性时不变系统的一种线性控制方法,…...
ubuntu环境下docker容器详细安装使用
文章目录 一、简介二、ubuntu安装docker1.删除旧版本2.安装方法一3. 安装方法二(推荐使用)4.运行Docker容器5. 配置docker加速器 三、Docker镜像操作1. 拉取镜像2. 查看本地镜像3. 删除镜像4. 镜像打标签5. Dockerfile生成镜像 四、Docker容器操作1. 获取…...
vue2源码分析-vue入口文件global-api分析
文章背景 vue项目开发过程中,首先会有一个初始化的流程,以及我们会使用到很多全局的api,如 this.$set this.$delete this.$nextTick,以及初始化方法extend,initUse, initMixin , initExtend, initAssetRegisters 等等那它们是怎么实现,让我们一起来探究下吧 源码目录 global-…...
Javascript原型 ,原型链如何理解使用 ?有什么特点?
文章目录 图解原型原型链总结有需要的请私信博主,还请麻烦给个关注,博主不定期更新,或许能够有所帮助!!请关注公众号 图解 原型 常被描述为 — 种基于原型的语言–每个对象拥有一个原型对象 当试图访问 一个对象的属性…...
Flutter混合栈管理方案对比
1.Google官方(多引擎方案) Google官方建议的方式是多引擎方案,即每次使用一个新的FlutterEngine来渲染Widget树,存在的主要问题是每个引擎都要有比较大的内存等资源消耗,虽然Flutter 2.0之后的FlutterEngineGroup通过在…...
Asp .Net Core 集成 Newtonsoft.Json
简介 Newtonsoft.Json是一个在.NET环境下开源的JSON格式序列化和反序列化的类库。它可以将.NET对象转换为JSON格式的字符串,也可以将JSON格式的字符串转换为.NET对象。这个类库在.NET开发中被广泛使用,因为它功能强大、易于使用,并且有良好的性能。 使用Newtonsoft.Json,…...
GPT对话知识库——ARM-Cortex架构分为哪几个系列?每个系列有几种工作模式?各种工作模式之间的定义和区别?每种架构不同的特点和应用需求?
目录 1,问: 1,答: 2,问: 2,答: Cortex-A系列 Cortex-R系列 Cortex-M系列 3,问: 3,答: ARM Cortex-A架构 ARM Cortex-R架构…...
795. 前缀和(acwing)
文章目录 795.前缀和题目描述前缀和 795.前缀和 题目描述 输入一个长度为n的整数序列。 接下来再输入m个询问,每个询问输入一对l, r。 对于每个询问,输出原序列中从第l个数到第r个数的和。 输入格式 第一行包含两个整数n和m。 第二行包含n个整数&a…...
1910_野火FreeRTOS教程阅读笔记_prvStartFirstTask函数
1910_野火FreeRTOS教程阅读笔记_prvStartFirstTask函数 全部学习汇总: g_FreeRTOS: FreeRTOS学习笔记 这是教程中的一个函数,通过汇编来实现的。注释部分以及结合后面的讲解部分,可能还是有一点点细节的地方让初学者疑惑。我结合我自己的理解…...
图论练习5
Going Home Here 解题思路 模板 二分图最优匹配,前提是有完美匹配(即存在一一配对)左右集合分别有顶标,当时,为有效边,即选中初始对于左集合每个点,选择其连边中最优的,然后对于每…...
[C++] Volatile 和常量Const优化
Volatile的作用 volatile 表明某个变量的值可能在外部被改变,因此对这些变量的存取不能缓存到寄存器,每次使用时需要重新存取。 Const 和 Volatile的示例 示例1 int main() {const int a 1;int* pa const_cast<int*>(&a);*pa 4;cout &l…...
嵌入式学习day32 网络
htons();//host to network short 将端口号转换为网络通信中的大端存储 eg:htons(50000); ntohs();//host to network short 将大端存储转换为主机端口号 inet_addr();将IP地址转换为二进制 eg:inet_addr(192.168.1.170); inet_ntoa()…...
算法D33 | 贪心算法3 | 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果
1005.K次取反后最大化的数组和 本题简单一些,估计大家不用想着贪心 ,用自己直觉也会有思路。 代码随想录 Python: class Solution:def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:nums.sort(keylambda x: abs(x), reverseT…...
html地铁跑酷
下面是一个简单的HTML代码来展示一个地铁跑酷游戏: <!DOCTYPE html> <html> <head><title>地铁跑酷</title><style>#player {position: absolute;top: 0;left: 0;width: 50px;height: 50px;background-color: red;}</style…...
利用GPT开发应用001:GPT基础知识及LLM发展
文章目录 一、惊艳的GPT二、大语言模型LLMs三、自然语言处理NLP四、大语言模型LLM发展 一、惊艳的GPT 想象一下,您可以与计算机的交流速度与与朋友交流一样快。那会是什么样子?您可以创建哪些应用程序?这正是OpenAI正在助力构建的世界&#x…...
Golang Ants 构建协程池
构建的协程池实现两个目标: 1、限制协程池里开启的协程数量 2、当任务数大于协程数时,一个协程可以同时处理多个任务 3、监控是哪个协程ID处理了具体的任务 package mainimport ("fmt""runtime""strconv""string…...
【金三银四】面试题汇总(持续编写中)
Java八股文面试题汇总(持续编写中~) Java基础集合JUCJVM 数据库MySQLRedis 框架篇SSMSpringBoot 数据结构与算法数据结构与算法--汇总篇27道基础算法题,学完让你对算法有豁然开朗的感觉(推荐小白) 消息中间件RabbitMQK…...
Hive的数据存储
Hive的数据存储在HDFS的:/user/hive/warehouse中 The /user folder in HDFS is a directory typically used to store user-specific data and configurations. It serves as the home directory for Hadoop users, analogous to the /home directory in Unix-like …...
跨设备电子书同步终极指南:Koodo Reader 2.3.1完整教程
跨设备电子书同步终极指南:Koodo Reader 2.3.1完整教程 【免费下载链接】koodo-reader A modern ebook manager and reader with sync and backup capacities for Windows, macOS, Linux and Web 项目地址: https://gitcode.com/GitHub_Trending/koo/koodo-reader…...
ZLUDA技术破局:跨厂商GPU的CUDA生态兼容之道
ZLUDA技术破局:跨厂商GPU的CUDA生态兼容之道 【免费下载链接】ZLUDA CUDA on Intel GPUs 项目地址: https://gitcode.com/GitHub_Trending/zl/ZLUDA 作为开源兼容层领域的创新之作,ZLUDA正在重塑GPU计算生态格局。这款突破性工具通过专利的指令翻…...
开源小模型怎么选?Qwen1.5-0.5B-Chat轻量化优势解析
开源小模型怎么选?Qwen1.5-0.5B-Chat轻量化优势解析 1. 为什么需要轻量级小模型? 当我们谈论AI大模型时,很多人首先想到的是那些需要高端GPU、动辄几十GB内存的庞然大物。但在实际应用中,特别是个人开发者、中小企业或者教育场景…...
SiameseUIE在CSDN社区的应用:技术文章智能分析
SiameseUIE在CSDN社区的应用:技术文章智能分析 1. 引言 CSDN社区每天都有成千上万的技术文章发布,涵盖了从编程语言到人工智能的各个领域。面对如此庞大的内容量,如何快速准确地理解每篇文章的核心内容、自动生成标签、进行智能分类&#x…...
【AI图像创作变现】02提示词工程:从基础到精通的风格控制与商业应用
1. 提示词工程:AI图像创作的指挥棒 第一次接触AI绘图时,我像大多数人一样以为随便输入几个词就能得到完美作品。直到看到生成的"四不像"图片才明白,提示词不是许愿池,而是需要精确操作的调色盘。提示词工程本质上是用自…...
Electron应用打包体积优化实战:从30MB瘦身到15MB,我的electron-builder.yml配置清单
Electron应用打包体积优化实战:从30MB瘦身到15MB 最近在优化一个Electron应用的打包体积时,发现初始生成的安装包竟然达到了30MB。经过一系列配置调整和优化,最终成功将体积缩减到15MB。这个过程让我深刻体会到,electron-builder…...
OpenClaw备份策略:nanobot镜像的模型权重与技能配置定期同步
OpenClaw备份策略:nanobot镜像的模型权重与技能配置定期同步 1. 为什么需要备份OpenClaw工作区 上周我的开发机突然蓝屏,硬盘分区表损坏。当我发现过去三个月精心调教的OpenClaw技能配置和模型微调权重全部丢失时,那种痛彻心扉的感觉让我意…...
AIGlasses_for_navigation 模型微调教程:使用自定义数据适配特定场景
AIGlasses_for_navigation 模型微调教程:使用自定义数据适配特定场景 你是不是觉得,那些通用的导航模型,在工厂车间或者医院走廊里用起来,总有点“水土不服”?路线规划可能没错,但遇到一些特殊的设备、标识…...
HRN模型与PID控制结合:实时面部动画调节系统
HRN模型与PID控制结合:实时面部动画调节系统 1. 引言 想象一下,你正在制作一部动画电影,主角的面部表情需要精确到每一帧的微妙变化。传统的手工调整方式耗时耗力,而自动生成的表情又往往缺乏自然流畅的过渡。这就是为什么我们需…...
如何高效管理《神界:原罪2》模组?Divinity Mod Manager终极指南
如何高效管理《神界:原罪2》模组?Divinity Mod Manager终极指南 【免费下载链接】DivinityModManager A mod manager for Divinity: Original Sin - Definitive Edition. 项目地址: https://gitcode.com/gh_mirrors/di/DivinityModManager Divini…...
