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

网络编程 -------- 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 &#xff08;服务器的ip端口&#xff09; listen accept recv / send close Client.c socket connect &#xff08;服务器的ip端口&#xff09; …...

口袋奇兵:游戏辅助教程!陆军搭配阵容推荐,平民必备!

《口袋奇兵》是一款策略类手游&#xff0c;玩家需要在游戏中组建和指挥自己的军队&#xff0c;进行各种战斗和任务。为了在游戏中取得更好的成绩&#xff0c;合理搭配英雄和使用辅助工具是非常重要的。本攻略将为大家介绍一种强力的陆军搭配阵容&#xff0c;以及如何利用VMOS云…...

Spring Boot 集成参数效验 Validator

为什么需要参数效验? 在业务开发中,为了防止非法参数对业务造成影响,所以需要对用户输入的正确性、数据完整性、安全性、业务规则的执行做效验,靠代码对接口参数做if判断的话就太繁琐了,代码冗余且可读性差(主要是不够优雅)。 Validator效验框架遵循了JSR-303验证规范…...

63、ELK安装和部署

一、ELK日志系统 1.1、ELK平台的定义 ELK平台是一套完整的日志集中处理解决方案&#xff0c;将ElasticSearch、Logstash和Kiabana 三个开源工具配合使用&#xff0c;完成更强大的用户对日志的查询、排序、统计需求 E:elasticsearch ES分布式索引型非关系数据库&#xff0c;存…...

【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】格密码基础(例题较多,非常适合入门!)

格密码相关 文章目录 格密码相关格密码基本概念&#xff08;属于后量子密码&#xff09;基础的格运算&#xff08;行列式运算&#xff09;SVP&#xff08;shortest Vector Problem&#xff09;最短向量问题CVP&#xff08;Closet Vector Problem&#xff09;最近向量问题 做题要…...

Java对象流

对象流 对象输入流 java.io.ObjectInputStream使用对象流可以进行对象反序列化 构造器 ObjectInputStream(InputStream in) 将当前创建的对象输入流链接在指定的输入流上 方法 Object readObject() 进行对象反序列化并返回。该方法会从当前对象输入流链接的流中读取若干…...

问界M7是不是换壳东风ix7? 这下有答案了

文 | AUTO芯 作者 | 谦行 终于真相大白了 黑子们出来挨打啊 问界M7是换壳的东风ix7&#xff1f; 你们没想到&#xff0c;余大嘴会亲自出来正面回应吧 瞧瞧黑子当时乐的 问界你可以啊&#xff01;靠改名字造车呢&#xff1f; 还有更过分的&#xff0c;说M7是东风小康ix7…...

mybatis多条件in查询拓展

背景 最近碰上有个业务&#xff0c;查询的sql如下&#xff1a; select * from table where (sku_id,batch_no) in ((#{skuId},#{batchNo}),...); 本来也没什么&#xff0c;很简单常见的一种sql。问题是我们使用的是mybatis-plus&#xff0c;然后写的时候又没有考虑到后面的查…...

<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&#xff1a;基础例题 例题2&#xff1a;路径恢复 例题3&#xff1a;扩展…...

Python爬虫:下载人生格言

Python爬虫:下载人生格言 爬取网页 将这些格言下载存储到本地 代码: import requests #导入requests库&#xff0c;用于提取网页 from lxml import etree#导入lxml库&#xff0c;用于Xpath数据解析#请求头 header{ user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) A…...

使用注意力机制的seq2seq

一、背景 1、机器翻译中&#xff0c;每个生成的词可能相关于源句子中不同的词&#xff0c;但是之前用的是最后一个RNN层出来的context。 2、加入注意力 &#xff08;1&#xff09;假设输入序列中有&#x1d447;个词元&#xff0c; 解码时间步&#x1d461;′的上下文变量是…...

我们的前端开发逆天了!1 小时搞定了新网站,还跟我说 “不要钱”

大家好&#xff0c;我是程序员鱼皮。前段时间我们上线了一个新软件 剪切助手 &#xff0c;并且针对该项目做了一个官网&#xff1a; 很多同学表示官网很好看&#xff0c;还好奇是怎么做的&#xff0c;其实这个网站的背后还有个有趣的小故事。。。 鱼皮&#xff1a;我们要做个官…...

.NET 相关概念

.NET 和 .NET SDK .NET 介绍 .NET 是一个由 Microsoft 开发和维护的广泛用于构建各种类型应用程序的开发框架。它是一个跨平台、跨语言的开发平台&#xff0c;提供了丰富的类库、API和开发工具&#xff0c;支持开发者使用多种编程语言&#xff08;如C#、VB.NET、F#等&#xf…...

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&#xff08;自行下载即可&#xff09;&#xff1a;高德地图离线解决方案: 高德地图离线解决方案 然因为高德地图的瓦片地图太大&#xff0c;所以要让后端部署下 前端直接调用 如果本地 直接找到瓦片图路径就可以 initMap () {const base_url "…...

springboot 集成私有化Ollama大模型开源框架,搭建AI智能平台

Ollama是一个用于大数据和机器学习的平台&#xff0c;它可以帮助企业进行数据处理、分析和决策制定。 &#xff11;、在Spring Boot项目pom.xml中添加Ollama客户端库依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-a…...

6.key的层级结构

redis的key允许多个单词形成层级结构&#xff0c;多个单词之间用:隔开&#xff0c;格式如下&#xff1a; 项目名:业务名:类型:id 这个格式并非固定的&#xff0c;可以根据自己的需求来删除或添加词条。 例如&#xff1a; taobao:user:1 taobao:product:1 如果value是一个java对…...

LogonTracer图形化事件分析工具

LogonTracer这款工具是基于Python编写的&#xff0c;并使用Neo4j作为其数据库&#xff08;Neo4j多用于图形数据库&#xff09;&#xff0c;是一款用于分析Windows安全事件登录日志的可视化工具。它会将登录相关事件中的主机名&#xff08;或IP地址&#xff09;和帐户名称关联起…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

FFmpeg avformat_open_input函数分析

函数内部的总体流程如下&#xff1a; avformat_open_input 精简后的代码如下&#xff1a; int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...