网络编程 -------- 3、TCP_UDP_UNIX
1、基于TCP的套接字编程流程
Server.c
socket
bind (服务器的ip+端口)
listen
accept
recv / send
close
Client.c
socket
connect (服务器的ip+端口)
send / recv
close
扩展:
(1) 三路握手: TCP建立连接时
1)SYN请求 (客户端-->服务器)
2)SYN+ACK应答 (服务器-->客户端)
3)ACK确认 (客户端-->服务器)
(2) 四次挥手: TCP断开连接时
1)FIN请求 (客户端-->服务器)
2)ACK应答 (服务器-->客户端)
3)FIN请求 (服务器-->客户端)
4)ACK应答 (客户端-->服务器)
2、基于UDP的套接字编程流程
Server.c
socket
bind (服务器的ip+端口)
recvfrom / sendto
close
Client.c
socket
//设置服务器的ip和端口
sendto / recvfrom
close
利用UDP 实现简单的通信 UDP ---> SOCK_DGRAM 数据报套接字类型udp_server.c 接收数据 int main( int argc, char *argv[] ){//1.创建套接字 UDP ---> SOCK_DGRAM 数据报套接字int server_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( server_fd == -1 ){perror("socket server error ");return -1;}printf("server_fd = %d\n", server_fd );//2.绑定服务器的ip和端口struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号inet_aton( argv[1], &server_addr.sin_addr ); //IP地址int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("bind server error ");return -1;}printf("bind server success\n");//3.通信 while( 1 ){//接收数据 char buf[128] = {0};struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);re = recvfrom( server_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len );if( re >= 0 ){printf("%s : %s\n", inet_ntoa(client_addr.sin_addr), buf );}else {perror("recvfrom server error ");break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//4.关闭套接字close( server_fd );}udp_client.c 发送数据 int main( int argc, char *argv[] ){//1.创建套接字 UDP ---> SOCK_DGRAM 数据报套接字int client_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( client_fd == -1 ){perror("socket client error ");return -1;}printf("client_fd = %d\n", client_fd );//2.设置服务器的ip和端口struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号inet_aton( argv[1], &server_addr.sin_addr ); //IP地址//3.通信 while(1){//发送数据 char buf[128] = {0};printf("input data : ");fgets(buf, sizeof(buf), stdin);int re = sendto( client_fd, buf, strlen(buf), 0, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("sendto error ");break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//4.关闭套接字close( client_fd );}
3、UNIX域协议
UNIX域协议是利用socket编程接口 来实现 本地进程之间(客户端/服务器)的通信,它是进程间通信(IPC)的一种方式。它使用文件系统中的路径名来标识服务器和客户端。
UNIX域协议的套接字:
SOCK_STREAM ---> TCP 面向字节流
SOCK_DGRAM ---> UDP 面向数据报
其编程接口 和 流程 与 ipv4协议族是一样的
只不过 协议族为 AF_UNIX , 对应的地址结构体为
UNIX域协议地址结构体 ( man 7 unix )
#include <sys/un.h>
struct sockaddr_un
{
sa_family_t sun_family; /* 协议族 AF_UNIX */
char sun_path[108]; /* UNIX域协议的地址,在本地文件系统中的“绝对路径名” pathname */
};
#define UNIX_PATH "/home/china/unix2418F"
实现方法: UDP / TCP
练习: 利用UNIX域协议 实现简单的通信 (以UDP为例)unix_server.c 接收数据 int main( int argc, char *argv[] ){//删除 unlink( UNIX_PATH );//1.创建套接字 AF_UNIX int server_fd = socket( AF_UNIX, SOCK_DGRAM, 0 );if( server_fd == -1 ){perror("socket server error ");return -1;}//2.绑定 服务器的地址 struct sockaddr_un server_addr;server_addr.sun_family = AF_UNIX; //协议族 strcpy( server_addr.sun_path, UNIX_PATH ); //unix域协议的地址int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("bind server error ");close( server_fd );return -1;}printf("bind server success\n");struct sockaddr_un client_addr;socklen_t len = sizeof(client_addr);//3.通信 while(1){//接收数据 char buf[128] = {0};re = recvfrom( server_fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &len );if( re >= 0 ){printf("recv : %s\n", buf );}else {perror("recvfrom server error ");break;}if( buf[0] == '#' ){break;}}//4.关闭套接字close( server_fd );}unix_client.c 发送数据 //1.创建套接字 //2.设置服务器的地址 //3.通信 //4.关闭套接字
4、套接字选项
套接字选项是用来设置或获取套接字的一些特性的选项。
每个套接字在不同的层次上(级别) 有不同的行为属性(选项)
有两个接口函数用来 获取和设置 套接字的选项:
getsockopt
setsockopt
NAME
getsockopt, setsockopt - get and set options on sockets
SYNOPSIS
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
功能:获取/设置套接字的选项
参数:
sockfd:指定要操作的套接字描述符
level:级别,不同的选择在不同的级别上(查看资料)
optname:选项名
optval: 通用指针
get 用来保存获取到的选项值
set 用来保存要设置的选项值
不同的选项 对应的类型是不一样的
如果为 int ---> 0 禁用选项
--> 非0 使能选项
optlen:
get 指针,指向空间保存选项值的空间的长度
set 变量,用来指定要设置的选项值的长度
返回值:
成功,返回0
失败,返回-1,同时errno被设置
设置 端口号重用 选项名: SO_REUSEPORT 级别: SOL_SOCKET值的类型: int /设置端口号重用 int n = 1;setsockopt( server_sock, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n) );
5、UDP的例子 (拓展)
1)DNS : Domain Name System 域名系统
www.baidu.com ----> 域名
DNS:是把一个域名 转换成 相应的ip地址的服务
DNS协议 传输层用到UDP协议
DNS Server
ip: 114.114.114.114
端口 53
2)NTP : Network Time Protocol 网络时间协议
基于UDP的传输层协议
服务器:
阿里云 : 182.92.12.11
端口: 123
利用TCP 写一个网络传输文件的程序 file_tcp_server.c 服务器 接收文件 file_tcp_client.c 客户端 发送文件 注意: 通信双方 发送和接收的 数据、大小、顺序 要保持一致 遵守通信双向的约定 ---> "协议"file_tcp_server.c 服务器 接收文件 int recv_file( int sock_fd ){//切换路径 chdir("../");//接收文件名的长度大小 int name_len = 0;int re = recv( sock_fd, &name_len, sizeof(name_len), 0 );if( re == -1 ){perror("recv name_len error "); return -1;}printf("recv name_len success , len = %d\n", name_len );//接收文件名char filename[128] = {0};re = recv( sock_fd, filename, name_len, 0 );if( re == -1 ){perror("recv filename error ");return -1;}printf("recv filename success , filename = %s\n", filename );//接收文件的大小 int file_size = 0;re = recv( sock_fd, &file_size, sizeof(file_size), 0 );if( re == -1 ){perror("recv file_size error ");return -1;}printf("recv file_size success , file_size = %d\n", file_size );/* 接收文件的内容创建并打开文件接收数据写入文件关闭文件*///创建并打开文件int fd = open( filename, O_RDWR | O_CREAT | O_EXCL, 0666 );if( fd == -1 ){if( errno == EEXIST ) //文件已经存在,就直接打开即可{fd = open( filename, O_RDWR | O_TRUNC );}else {perror("open file error ");return -1;}}int write_size = 0; //已经写入的字节数while( write_size < file_size ){//先接收数据 char buf[128] = {0};re = recv( sock_fd, buf, 100, 0 );if( re > 0 ){//写入文件 write( fd, buf, re );write_size += re;}else {perror("recv file error ");break;}}if( write_size == file_size ){printf("recv file success\n");}else {printf("recv file failed \n");}//关闭文件 close( fd );}int main( int argc, char *argv[] ){//1.创建套接字 int server_fd = socket( AF_INET, SOCK_STREAM, 0 );if( server_fd == -1 ){perror("socket server error ");return -1;}printf("server_fd = %d\n", server_fd );//2.绑定 服务器的ip和端口struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号inet_aton( argv[1], &server_addr.sin_addr ); //IP地址//设置端口号重用int n = 1;setsockopt( server_fd, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n) );int re = bind( server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("bind server error ");close( server_fd );return -1;}printf("bind server success\n");//3.监听 re = listen( server_fd, 5 );if( re == -1 ){perror("listen server error ");close( server_fd ); return -1;}printf("listen server success\n");//4.接受连接 struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);int client_fd = accept( server_fd, (struct sockaddr *)&client_addr, &len );if( client_fd == -1 ){perror("accept error ");close( server_fd );return -1;}printf("client_fd = %d\n", client_fd );printf("client_ip = %s\n", inet_ntoa(client_addr.sin_addr) );//5.通信 -->接收文件 recv_file( client_fd );//6.关闭套接字 close( server_fd );}file_tcp_client.c 客户端 发送文件 int send_file( int sock_fd, char * filename ){//发送文件名的长度大小 int name_len = strlen(filename);int re = send( sock_fd, &name_len, sizeof(name_len), 0 );if( re == -1 ){perror("send name_len error ");return -1;}printf("send name_len success , len = %d\n", name_len );//发送文件名 re = send( sock_fd, filename, name_len, 0 );if( re == -1 ){perror("send filename error ");return -1;}printf("send filename success , filename = %s\n", filename );//发送文件的大小struct stat st;stat( filename, &st ); //获取文件属性-->文件大小 int file_size = st.st_size;re = send( sock_fd, &file_size, sizeof(file_size), 0 );if( re == -1 ){perror("send file_size error ");return -1;}printf("send file_size success , file_size = %d\n", file_size );/* 发送文件的内容 打开文件读取发送 关闭文件 *///打开文件int fd = open( filename, O_RDONLY );if( fd == -1 ){perror("open file error ");return -1;}int read_size = 0; //已经读取到的字节数while( read_size < file_size ){//先读取文件内容 char buf[128] = {0};re = read( fd, buf, 100 );if( re > 0 ){//发送数据 send( sock_fd, buf, re, 0 );read_size += re;}else {perror("read file error ");break;}}if( read_size == file_size ){printf("send file success\n");}else {printf("send file failed \n");}//关闭文件 close( fd );}int main( int argc, char *argv[] ){//1.创建套接字 int client_fd = socket( AF_INET, SOCK_STREAM, 0 );if( client_fd == -1 ){perror("socket client error "); return -1;}printf("client_fd = %d\n", client_fd );//2.设置服务器的ip和端口struct sockaddr_in server_addr;server_addr.sin_family = AF_INET; //协议族 server_addr.sin_port = htons( atoi(argv[2]) ); //端口号inet_aton( argv[1], &server_addr.sin_addr ); //IP地址//3.连接服务器 int re = connect( client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr) );if( re == -1 ){perror("connect error ");close( client_fd );return -1;}printf("connect success\n");//4.通信 --> 发送文件 send_file( client_fd, argv[3] );//5.关闭套接字close( client_fd );}
相关文章:
网络编程 -------- 3、TCP_UDP_UNIX
1、基于TCP的套接字编程流程 Server.c socket bind (服务器的ip端口) listen accept recv / send close Client.c socket connect (服务器的ip端口) …...
口袋奇兵:游戏辅助教程!陆军搭配阵容推荐,平民必备!
《口袋奇兵》是一款策略类手游,玩家需要在游戏中组建和指挥自己的军队,进行各种战斗和任务。为了在游戏中取得更好的成绩,合理搭配英雄和使用辅助工具是非常重要的。本攻略将为大家介绍一种强力的陆军搭配阵容,以及如何利用VMOS云…...
Spring Boot 集成参数效验 Validator
为什么需要参数效验? 在业务开发中,为了防止非法参数对业务造成影响,所以需要对用户输入的正确性、数据完整性、安全性、业务规则的执行做效验,靠代码对接口参数做if判断的话就太繁琐了,代码冗余且可读性差(主要是不够优雅)。 Validator效验框架遵循了JSR-303验证规范…...
63、ELK安装和部署
一、ELK日志系统 1.1、ELK平台的定义 ELK平台是一套完整的日志集中处理解决方案,将ElasticSearch、Logstash和Kiabana 三个开源工具配合使用,完成更强大的用户对日志的查询、排序、统计需求 E:elasticsearch ES分布式索引型非关系数据库,存…...
【Dash】简单的直方图
一、Visualizing Data The Plotly graphing library has more than 50 chart types to choose from. In this example, we will make use of the histogram chart. # Import packages from dash import Dash, html, dash_table, dcc import pandas as pd import plotly.expre…...
【CTF-Crypto】格密码基础(例题较多,非常适合入门!)
格密码相关 文章目录 格密码相关格密码基本概念(属于后量子密码)基础的格运算(行列式运算)SVP(shortest Vector Problem)最短向量问题CVP(Closet Vector Problem)最近向量问题 做题要…...
Java对象流
对象流 对象输入流 java.io.ObjectInputStream使用对象流可以进行对象反序列化 构造器 ObjectInputStream(InputStream in) 将当前创建的对象输入流链接在指定的输入流上 方法 Object readObject() 进行对象反序列化并返回。该方法会从当前对象输入流链接的流中读取若干…...
问界M7是不是换壳东风ix7? 这下有答案了
文 | AUTO芯 作者 | 谦行 终于真相大白了 黑子们出来挨打啊 问界M7是换壳的东风ix7? 你们没想到,余大嘴会亲自出来正面回应吧 瞧瞧黑子当时乐的 问界你可以啊!靠改名字造车呢? 还有更过分的,说M7是东风小康ix7…...
mybatis多条件in查询拓展
背景 最近碰上有个业务,查询的sql如下: select * from table where (sku_id,batch_no) in ((#{skuId},#{batchNo}),...); 本来也没什么,很简单常见的一种sql。问题是我们使用的是mybatis-plus,然后写的时候又没有考虑到后面的查…...
<Rust><iced>基于rust使用iced构建GUI实例:一个CRC16校验码生成工具
前言 本专栏是Rust实例应用。 环境配置 平台:windows 软件:vscode 语言:rust 库:iced、iced_aw 概述 本文是专栏第五篇实例,是一个CRC16校验码转换程序。 本篇内容: 1、CRC16校验码生成 代码介绍 本文的crc16校验码生成工具,主要设计两个方面,一个是crc16 modbus…...
动态规划与0/1背包问题:深入解析
目录 一、动态规划简介 二、0/1背包问题概述 三、动态规划解决0/1背包问题 1. 定义子问题 2. 确定状态 3. 初始条件和边界情况 4. 计算最终结果 5. 代码实现 6. 空间优化 四、例题讲解 例题1:基础例题 例题2:路径恢复 例题3:扩展…...
Python爬虫:下载人生格言
Python爬虫:下载人生格言 爬取网页 将这些格言下载存储到本地 代码: import requests #导入requests库,用于提取网页 from lxml import etree#导入lxml库,用于Xpath数据解析#请求头 header{ user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) A…...
使用注意力机制的seq2seq
一、背景 1、机器翻译中,每个生成的词可能相关于源句子中不同的词,但是之前用的是最后一个RNN层出来的context。 2、加入注意力 (1)假设输入序列中有𝑇个词元, 解码时间步𝑡′的上下文变量是…...
我们的前端开发逆天了!1 小时搞定了新网站,还跟我说 “不要钱”
大家好,我是程序员鱼皮。前段时间我们上线了一个新软件 剪切助手 ,并且针对该项目做了一个官网: 很多同学表示官网很好看,还好奇是怎么做的,其实这个网站的背后还有个有趣的小故事。。。 鱼皮:我们要做个官…...
.NET 相关概念
.NET 和 .NET SDK .NET 介绍 .NET 是一个由 Microsoft 开发和维护的广泛用于构建各种类型应用程序的开发框架。它是一个跨平台、跨语言的开发平台,提供了丰富的类库、API和开发工具,支持开发者使用多种编程语言(如C#、VB.NET、F#等…...
Kubernetes 从集群中移除一个节点(Node)
目录 1. 移除工作节点(Worker Node)1.1 确定工作节点名称1.2 驱逐工作节点上的Pod1.3 删除工作节点1.4 重置该工作节点 2. 移除控制平面节点(Control Plane Node)2.1 确定控制平面节点名称2.2 驱逐控制平面节点上的Pod2.3 更新 etcd 集群2.4 从集群中删除控制平面节点2.5 重置移…...
高德地图离线版 使用高德地图api的方法
高德离线包我已经存至Gitee(自行下载即可):高德地图离线解决方案: 高德地图离线解决方案 然因为高德地图的瓦片地图太大,所以要让后端部署下 前端直接调用 如果本地 直接找到瓦片图路径就可以 initMap () {const base_url "…...
springboot 集成私有化Ollama大模型开源框架,搭建AI智能平台
Ollama是一个用于大数据和机器学习的平台,它可以帮助企业进行数据处理、分析和决策制定。 1、在Spring Boot项目pom.xml中添加Ollama客户端库依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-a…...
6.key的层级结构
redis的key允许多个单词形成层级结构,多个单词之间用:隔开,格式如下: 项目名:业务名:类型:id 这个格式并非固定的,可以根据自己的需求来删除或添加词条。 例如: taobao:user:1 taobao:product:1 如果value是一个java对…...
LogonTracer图形化事件分析工具
LogonTracer这款工具是基于Python编写的,并使用Neo4j作为其数据库(Neo4j多用于图形数据库),是一款用于分析Windows安全事件登录日志的可视化工具。它会将登录相关事件中的主机名(或IP地址)和帐户名称关联起…...
Qwen3-ASR-0.6B WebUI实战:中文方言自动识别与结果导出操作
Qwen3-ASR-0.6B WebUI实战:中文方言自动识别与结果导出操作 1. 快速了解Qwen3-ASR-0.6B语音识别模型 Qwen3-ASR-0.6B是一个轻量级但性能强大的语音识别模型,专门为实际应用场景设计。这个模型只有6亿参数,但识别效果却相当出色,…...
免环境配置:Qwen-Image定制镜像让4090D显卡快速跑通视觉语言模型
免环境配置:Qwen-Image定制镜像让4090D显卡快速跑通视觉语言模型 1. 引言 1.1 视觉语言模型的应用价值 在当今AI技术快速发展的背景下,视觉语言模型(VLM)已成为连接计算机视觉与自然语言处理的桥梁。这类模型能够理解图像内容并生成相关文本描述&…...
【Python工业视觉性能跃迁指南】:3大编译优化+5个CUDA加速技巧,让检测速度提升8.7倍
第一章:Python工业视觉性能跃迁的底层逻辑与评估体系Python在工业视觉领域长期面临“高表达性”与“低实时性”的根本矛盾。性能跃迁并非单纯依赖硬件升级或框架切换,而源于对计算图编译、内存布局优化、异构加速调度及IO瓶颈解耦四维协同机制的系统性重…...
Golang错误处理实战:defer、panic和recover的正确打开方式(附避坑指南)
Golang错误处理实战:defer、panic和recover的正确打开方式(附避坑指南) 在Golang的世界里,错误处理是一门艺术。与传统的try-catch机制不同,Go采用了独特的defer-panic-recover组合拳。这种设计哲学体现了Go语言"…...
COMSOL 探索岩石力学多场景:损伤、压裂、试验与模拟
COMSOL岩石损伤、水力压裂、三轴试验 岩石在膨胀剂的膨胀作用下的损伤; 相场法与水力压裂(6个模型); 不固结不排水三轴试验; 二维钻孔封孔效果模拟。在岩石力学领域,COMSOL 如同一个强大的实验室,让我们能够对复杂的岩…...
JPEXS Free Flash Decompiler技术文档贡献者名单:作者与编辑
JPEXS Free Flash Decompiler技术文档贡献者名单:作者与编辑 【免费下载链接】jpexs-decompiler JPEXS Free Flash Decompiler 项目地址: https://gitcode.com/gh_mirrors/jp/jpexs-decompiler JPEXS Free Flash Decompiler是一款强大的开源Flash反编译工具&…...
s2-pro语音合成教程:支持数字/单位/英文缩写智能朗读技巧
s2-pro语音合成教程:支持数字/单位/英文缩写智能朗读技巧 1. 快速了解s2-pro语音合成 s2-pro是Fish Audio开源的专业级语音合成模型镜像,它能将文本转换为自然流畅的语音。这个工具特别适合需要语音播报、有声读物制作、视频配音等场景的用户。 与普通…...
物理海洋学入门:从海浪到海流,一文搞懂海水运动的7种形式
物理海洋学入门:从海浪到海流,一文搞懂海水运动的7种形式 海洋覆盖了地球71%的表面积,这片蔚蓝的水域从未停止过运动。当我们站在海边,看着潮起潮落、浪花拍岸,或许会好奇:这些看似简单的海水运动背后&…...
3步搞定ERPNext自动化部署:让企业管理系统安装变得简单
3步搞定ERPNext自动化部署:让企业管理系统安装变得简单 【免费下载链接】erpnext_quick_install Unattended install script for ERPNext Versions, 13, 14 and 15 项目地址: https://gitcode.com/gh_mirrors/er/erpnext_quick_install 还在为复杂的ERPNext安…...
Mac开发者必备:OpenClaw调试QwQ-32B代码补全全流程
Mac开发者必备:OpenClaw调试QwQ-32B代码补全全流程 1. 为什么选择OpenClaw作为代码助手 作为一名长期在Mac上开发的全栈工程师,我一直在寻找能够真正融入工作流的智能编码工具。直到遇到OpenClaw,才发现这个开源的本地化AI智能体框架完美契…...
