net、udp、tcp

news2024/11/14 0:48:18

Makefile的main.c文件中的全局变量SONG song,要在fun.c文件里面写成extern SONG song

编译方法

第一次编写


网络编程 

物理层的网线规定有八根,颜色不一样,功能不一样,光猫把光信号转换成电信号,光纤10Gb

WiFi叫无线局域网,一般也就50米左右,手机流量叫蜂窝网络,随时随地上网。

链路层:先格式化一下,网络可以通过交换机连接起来。

网络层:通过ip地址找到目标

传输层:数据以何种方式传输?tcp可靠传输,传输过程中数据准确的到达对方。udp可能会丢包 。一般下载文件上传文件多以tcp为主,一般视频,音频 (实时性重要)一般用udp

OSI模型

物理层

解决两个硬件之间怎么通信的问题,常见的物理媒介有光纤、电缆、中继器等。它主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。

它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换)。这一层的数据叫做比特。

链路层(把设备连接起来)

在计算机网络中由于各种干扰的存在,物理链路是不可靠的。该层的主要功能就是:通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路。

它的具体工作是接收来自物理层的位流形式的数据,并封装成帧,传送到上一层;同样,也将来自上层的数据帧,拆装为位流形式的数据转发到物理层。这一层的数据叫做帧。

网络层

计算机网络中如果有多台计算机,怎么找到要发的那台?如果中间有多个节点,怎么选择路径?这就是路由要做的事。

该层的主要任务就是:通过路由选择算法,为报文(该层的数据单位,由上一层数据打包而来)通过通信子网选择最适当的路径。这一层定义的是IP地址,通过IP地址寻址,所以产生了IP协议。

传输层

当发送大量数据时,很可能会出现丢包的情况,另一台电脑要告诉是否完整接收到全部的包。如果缺了,就告诉丢了哪些包,然后再发一次,直至全部接收为止。

简单来说,传输层的主要功能就是:监控数据传输服务的质量,保证报文的正确传输。

会话层(网络断开,连接的状态)

虽然已经可以实现给正确的计算机,发送正确的封装过后的信息了。但我们总不可能每次都要调用传输层协议去打包,然后再调用IP协议去找路由,所以我们要建立一个自动收发包,自动寻址的功能。于是会话层出现了:它的作用就是建立和管理应用程序之间的通信。

表示层(加密,解密)

表示层负责数据格式的转换,将应用处理的信息转换为适合网络传输的格式,或者将来自下一层的数据转换为上层能处理的格式。

应用层

应用层是计算机用户,以及各种应用程序和网络之间的接口,其功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作。前端同学对应用层肯定是最熟悉的。

TCP/IP模型(也叫tcp/ip协议栈):专门描述互联网的模型(把OSI模型合并了一下)

TCP/IP协议族

  • dns 域名解析  把域名转成ip地址
  • DHCP 动态主机配置协议(路由器分配地址)
  • http  超文本传输协议(使用网页就会用到这个协议)
  • FTP  互联网远距离传输用ftp(可以断点续传)
  • TFTP 简单文件传输协议(传输本地文件)---局域网内
  • SNMP   网络管理  网络状态监测
  • TCP 传输控制协议   一种可靠的传输方式  自带超时重传   必须要有应答    实时性比较差
  • UDP   实时性好  会丢包   节省网络开销
  • ARP  地址解析协议    在以太网环境中,数据的传输所依懒的是MAC地址而非IP地址,而将已知IP地址转换为MAC地址的工作是由ARP协议来完成的。
  • RIP和OSPF都是路由协议

TCP编程基础知识


  • 网关:也叫gate,跟个门一样,没出去就是局域网,出去就是互联网,默认是0.1(后两位)
  • 广播:最后一位是255)给这个位发,所有人都接收到了(只能是局域网里,一个人发所有人收)
  • 组播:让想收到的人收到(类似于群聊)

IP地址一般都是点分十进制(分为四段,每一段最小0最大255)

A类中第一段表示有多少个网络,是网络号,后面的数字表示有多少台主机(2的64次方)

B类中前两段表示有多少个网络(比如说128.0和128.1代表两个网络),后面数字表示有多少台主机(2的16次方)

C类前三段表示有多少个网络,后面数字表示有某一台主机(主机号)------我们一般用的是这种

linux的网络配置命令

配置完一定要重启sudo reboot 才会生效

ifconfig:查看网卡状态相关信息

硬件地址

手动设置ip地址,然后重启

查看网络状态(是否连接)

网络接口

  • socket 套接字  是文件描述符(网络文件需要收发)
  • ip地址是用来找主机的
  • 端口号用来识别进程的

网络字节序

小端存储--数据的低位在低内存

  • 计算机是小端    网络设备是大端
  • ip地址和端口号要去找主机设备--------都要大小端转换一下

UDP(有服务端和客户端,一对多的关系)简单一点----无连接,不显示状态信息,不可靠

  • socket类似于open,将网络设备打开,打开后拿到一个文件描述符
  • 客户端找服务器需要ip地址和端口号,bind就是给套接字设置ip地址和端口号的 
  • 服务器先收,因为客户得先告诉服务器要啥

代码:(客户端找服务器)

固定的就选这个IPv4对应的

服务端: 

SA是强转一下,转成下面这个类型

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);//第一步,可能会有少量丢包,0是默认方式
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;//in代表internet互联网,这个是对方和自己的地址结构体
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);//小端转大端,50000是端口号
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");//写自己ip,大端转小端,数字转字符串
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));//第二步,绑定
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    while(1)
    {
        char buf[512]={0};
        recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);//第三步,收,0代表工作方式,有人发就接受,没人就等着
        time_t tm;
        time(&tm);//拿到时间
        sprintf(buf,"%s %s",buf,ctime(&tm));
        sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);//第四步,发出去,0是默认方式
    }
    close(sockfd);
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);


int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);//第一步
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");

    while(1)
    {
        char buf[512]="hello,this is udp test";
        sendto(sockfd,buf,strlen(buf),0,(SA)&ser,sizeof(ser));//第二步
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);//第三步
        printf("buf is %s\n",buf);
        sleep(1);
    }
    close(sockfd);
    return 0;
}

 结果:

UDP(用户数据报)(半双工,要么收要么发)

 发完链路就自动释放了,比较节省空间,网络开销比较小,丢包就是因为没有维护链路的状态

数据报:数据和数据间是有间隔的,收发次数要对应,不然就丢了,并且在收的大小建议大于等于包的大小,即使小了,剩下的也不会再收到了

UDP特征

  • 数据有边界
  • 收发次数要对应
  • recvfrom如果没有发送,就会阻塞
  • sendto不会阻塞,他只管发,收不收都可以

UDP传文件的代码

服务端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr * (SA);
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    //ser.sin_addr.s_addr = inet_addr("127.0.0.1");//活的地址,也代表自己的地址,本地回环,自己跟自己测,这个数据不会发出去
    ser.sin_addr.s_addr = INADDR_ANY;//代表本机任何一个可用的IP地址,自己跟自己也可以,跟外面也可以,不用大小端转换
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    int fd = open("2.png",O_WRONLY|O_CREAT|O_TRUNC,0666);//trunc是清空,只要有创建后面就给666
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }
    while(1)
    {
        char buf[512]={0};
        int rd_ret = recvfrom(sockfd,buf,sizeof(buf),0,(SA)&cli,&len);
        if(0 == strcmp(buf,"^_^"))
        {
            break;
        }
        write(fd,buf,rd_ret);//收多少写多少
        bzero(buf,sizeof(buf));
        strcpy(buf,"go on");//防止发的太快来不及写(收),所以控制他发的速度
        sendto(sockfd,buf,strlen(buf),0,(SA)&cli,len);
    }
    close(sockfd);
    close(fd);
    return 0;
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
#include <fcntl.h>
typedef struct sockaddr * (SA);


int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in ser;
    bzero(&ser,sizeof(ser));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("192.168.203.128");//自己跟自己可以写any,跟别的必须写客户端IP地址
    int fd = open("/home/linux/1.png",O_RDONLY);
    if(-1 == fd)
    {
        perror("open");
        exit(1);
    }
    char buf[512]={0};
    while(1)
    {
        bzero(buf,sizeof(buf));
        int rd_ret = read(fd,buf,sizeof(buf));
        if(0==rd_ret)
        {
            break;
        }
        sendto(sockfd,buf,rd_ret,0,(SA)&ser,sizeof(ser));
        bzero(buf,sizeof(buf));
        recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
    }
    
    bzero(buf,sizeof(buf));
    strcpy(buf,"^_^");
    sendto(sockfd,buf,3,0,(SA)&ser,sizeof(ser));//走到这里证明发送结束了,告诉客户端发送结束了,因为无连接
    close(sockfd);
    close(fd);
    return 0;
}

结果:

练习:UDP的聊天室(一个人发,全都能收到)

服务端是负责转发的,除了不给发消息的人转发,其他人都转

服务端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct sockaddr * (SA);
typedef enum {CMD_LOGIN,CMD_CHAT,CMD_LOGOUT}TYPE;
typedef struct 
{
    TYPE type;
    char name[50];
    char context[128];

}MSG;
typedef struct 
{
    struct sockaddr_in cli;
    int flag; // 0  free 1 occu
}LIST;
#define MAX 10
LIST list[MAX]={0};//最多多少人
int do_login(int sockfd,MSG* msg,struct sockaddr_in* cli)
{
    int i = 0 ;
    for(i=0;i<MAX;i++)
    {
        if(1 == list[i].flag )//等于一证明人在,没退出
        {
            sendto(sockfd,msg,sizeof(MSG),0,(SA)&list[i].cli,sizeof(list[i].cli));
        }
    }
    for(i=0;i<MAX;i++)
    {
        if(0 == list[i].flag )
        {
            list[i].flag =1;
            //list[i].cli = *cli;
            memcpy(&list[i].cli,cli,sizeof(*cli));
            break;
        }
    }
    return 0;
}

int do_chat(int sockfd, MSG* msg,struct sockaddr_in*cli)//转发
{
     int i = 0 ;
    for(i=0;i<MAX;i++)
    {
        if(1 == list[i].flag && 0!=memcmp(&list[i].cli,cli,sizeof(*cli)) )//确保有人,并且发送方和接收方的ip地址不一样
        {
            sendto(sockfd,msg,sizeof(MSG),0,(SA)&list[i].cli,sizeof(list[i].cli));
        }
    }
}
int do_logout(int sockfd, MSG* msg,struct sockaddr_in*cli)
{
    return 0;
}
int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);
    if(-1 == sockfd)
    {
        perror("socket");
        exit(1);
    }

    // man 7 ip 
    struct sockaddr_in ser,cli;
    bzero(&ser,sizeof(ser));
    bzero(&cli,sizeof(cli));
    ser.sin_family = AF_INET;
    // 大小端转化 host to net short 
    ser.sin_port = htons(50000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");
    int ret = bind(sockfd,(SA)&ser,sizeof(ser));
    if(-1 == ret)
    {
        perror("bind");
        exit(1);
    }
    socklen_t len = sizeof(cli);
    MSG msg;
    while(1)
    {
        bzero(&msg,sizeof(msg));
        recvfrom(sockfd,&msg,sizeof(msg),0,(SA)&cli,&len);
        switch(msg.type)
        {
            case CMD_LOGIN:
                do_login(sockfd,&msg,&cli);
                break;
            case CMD_LOGOUT:
                do_logout(sockfd,&msg,&cli);
                break;
            case CMD_CHAT:
                do_chat(sockfd,&msg,&cli);
                break;
        
        }
    }
    close(sockfd);
    return 0;
}

客户端:(并行)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <time.h>
typedef struct 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101466.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无限延展(倒推法)

本题不妨逆推。 对于长度为的字符串 ,若要求第位的延展,考虑 在最后一次延展前的位置。 若延展结束后的长度为,每次考虑以下内容: 若 ​,说明本次伸展无效, ,

CTFHub技能树-备份文件下载-bak文件

当开发人员在线上环境中对源代码进行了备份操作&#xff0c;并且将备份文件放在了 web 目录下&#xff0c;就会引起网站源码泄露。 使用dirsearch扫描出index.php.bak 有些时候网站管理员可能为了方便&#xff0c;会在修改某个文件的时候先复制一份&#xff0c;将其命名为xxx.b…

没关系,会一手Git版本控制就行(全)

Git版本控制 文章目录 Git版本控制1. 版本控制1.1 概述1.2 版本控制优点1.3 本地版本控制系统&#xff08;离线版&#xff09;1.4 集中化的版本控制系统&#xff08;联网版&#xff09;1.5 分布式版本控制系统&#xff08;离线联网版&#xff09; 2. Git概述2.1 Git基本工作流程…

BUUCTF PWN wp--ciscn_2019_n_8

第一步 checksec一下&#xff0c;本题为32位。 分析一下保护机制&#xff1a; 一、RELRO: Partial RELRO Partial RELRO 提供了一定程度的保护。在这种情况下&#xff0c;部分重定位表在程序启动时被设置为只读。这可以防止一些针对重定位表的攻击&#xff0c;比如通过篡改重…

Elasticsearch 介绍

1、课程介绍 1.1 ES 8.x 演化进程 版本号发布日期多少个次要版本迭代历时8.02022年2月11日&#xff1f;至今7.02019年4月11日17个次要版本34个月6.02017年11月15日8个次要版本17个月5.02016年10月27日6个次要版本13个月 2、Elasticsearch 是什么 2.1 概念 2.1.1 标准定义 …

QLineEdit中文本显示不全,部分字符显示空白问题

环境 QT5.14.2 Windows 7 现象 触发某个条件后&#xff0c;使用QLineEdit的setText方法设置文本后&#xff0c;文本部分字符缺失&#xff0c;现象如下&#xff08;小数点后都是4位&#xff09;&#xff1a; 解决办法 设置根据显示器的像素密度进行自动缩放&#xff1b;再主…

VMware启动报错-Intel VT-x处于禁用状态,进入BIOS更改CPU设置

问题描述 VMware启动虚拟机失败&#xff0c;报错显示Intel VT-x处于禁用状态。 原因分析 打开主机的任务管理器&#xff0c;找到CPU&#xff0c;发现虚拟化处于禁用状态&#xff0c;查阅资料之后发现&#xff0c;进入BIOS模式将CPU虚拟化禁用开启即可解决。 解决步骤 1、…

KAN 学习 Day1 —— 模型框架解析及 HelloKAN

说明 最近了解到了一个新东西——KAN&#xff0c;我的毕设导师给推荐的船新框架。我看过很多剖析其原理的文章&#xff0c;发现大家对其持有的观点都各不相同&#xff0c;有的说可以颠覆传统MLP&#xff0c;有的说可以和Transformer同等地位&#xff0c;但是也有人说它训练速度…

15chatGLM3半精度微调

1 模型准备 数据依然使用之前的数据&#xff0c;但是模型部分我们使用chatglb-3&#xff0c;该模型大小6B&#xff0c;如果微调的话需要24*4 96GB,硬件要求很高&#xff0c;那么我们使用半精度微调策略进行调试&#xff0c;半精度微调有很多坑啊&#xff0c;注意别踩到…

只会SQL语句,可以做什么工作?

1、SQL是什么 首先简单介绍一下SQL&#xff08;Structured Query Language&#xff09;&#xff0c;是一种可以进行数据提取、聚合、分析&#xff0c;并对数据库进行构建和修改的编程语言。 相对来说&#xff0c;SQL上手非常容易&#xff0c;因为语法结构比较固定&#xff0c…

第一性原理计算从定义到场景到硬件配置详细讲解

第一性原理计算&#xff0c;又称为从头计算&#xff08;The Ab initio Calculation&#xff09;&#xff0c;是一种基于量子力学原理&#xff0c;通过计算机模拟来预测材料、分子、固体等体系性质的方法。这种方法的核心思想是不依赖于实验数据或经验参数&#xff0c;而是直接从…

如何纯手动的创建SpringBoot工程?

1、打开项目结构 2、new 一个新模块 3、所需全部选配好 4、 创建好之后&#xff0c;目录如下 5、在pom文件中&#xff0c;做第一件事情&#xff08;让当前的工程继承一个父工程&#xff09; &#xff08;这是一个固定的写法&#xff1a;spring-boot-starter-parent&#xff09;…

JavaWeb - Maven

Maven apache旗下的一个来源项目&#xff0c;一款用于管理和构建java项目的工具&#xff0c;它基于项目对象模型&#xff08;POM&#xff09;的概念&#xff0c;通过一小段描述信息来管理项目的构建。 作用 安装 解压官网下载的压缩包 配置本地仓库&#xff0c;修改conf/se…

接口请求400

接口请求400 在Web开发中&#xff0c;接口请求错误是开发者经常遇到的问题之一。其中&#xff0c;400错误&#xff08;Bad Request&#xff09;尤为常见&#xff0c;它表明发送到服务器的请求有误或不能被服务器理解。本文将深入探讨接口请求400错误&#xff0c;从常见报错问题…

springcloud微服务入门

1.架构的演变 目前我们接触的比较多的是单体架构&#xff0c;指的是将所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 这样的架构优点在于&#xff0c;架构简单&#xff0c;把各个功能集中在一起方便操作管理&#xff0c;部署成本也比较低但是缺点也是很明显&#…

让AI给你写代码(10.1): 按接口编程的思想,统一利用内部和外部的接口,逐步扩展和提升AI编程能力

先总结一下AI编程小助手已具备的能力&#xff0c;目前AI小助手已经可以利用本地知识库和在线大模型&#xff08;我们用的是qwen&#xff09;生成可测试&#xff0c;可执行代码的能力&#xff08;具体流程参考从让AI给你写代码&#xff08;9.1&#xff09;&#xff09;&#xff…

※※Leetcode Hot 100刷题记录 -Day8(和为k的子数组)

问题描述&#xff1a; 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a…

java开发面试:AOT有什么优缺点/适用于什么场景/AOT和JIT的对比、逃逸分析和对象存储在堆上的关系、高并发中的集合有哪些问题

JDK9引入了AOT编译模式。 AOT 有什么优点&#xff1f;适用于什么场景&#xff1f; JDK 9 引入了一种新的编译模式 AOT(Ahead of Time Compilation) 。 和 JIT 不同的是&#xff0c;这种编译模式会在程序被执行前就将其编译成机器码&#xff0c;属于静态编译&#xff08;C、 C…

【Redis详解】Redis安装+主从复制+哨兵模式+Redis Cluster

目录 一、Redis简介 1.1 关系型数据库和NoSQL数据库 二、Redis安装 2.1 rpm 安装 2.2 源码安装 三、Redis基本操作 四、Redis主从复制 4.1 配置主从同步 4.2 主从同步过程 五、Redis高可用--哨兵模式 5.1 哨兵的实验过程 六、数据保留 七、Redis Cluster 7.1 部署…

【办公软件】Excel如何开n次方根

在文章&#xff1a;【分立元件】电阻的基础知识中我们学习电阻值、电阻值容差标注相关标准。知道了标准将电阻值标准数列化。因此电阻值并非1Ω、2Ω、3Ω那样的整数&#xff0c;而是2.2Ω、4.7Ω那样的小数。 这是因为电阻值以标准数(E系列)为准。系列的“E”是Exponent(指数)…