当前位置: 首页 > 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;和帐户名称关联起…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...