net、udp、tcp

2024-09-03 20:52
文章标签 udp tcp net

本文主要是介绍net、udp、tcp,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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是清空,只要有创建后面就给666if(-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 

这篇关于net、udp、tcp的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134022

相关文章

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停

.NET利用C#字节流动态操作Excel文件

《.NET利用C#字节流动态操作Excel文件》在.NET开发中,通过字节流动态操作Excel文件提供了一种高效且灵活的方式处理数据,本文将演示如何在.NET平台使用C#通过字节流创建,读取,编辑及保... 目录用C#创建并保存Excel工作簿为字节流用C#通过字节流直接读取Excel文件数据用C#通过字节

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

2、PF-Net点云补全

2、PF-Net 点云补全 PF-Net论文链接:PF-Net PF-Net (Point Fractal Network for 3D Point Cloud Completion)是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像

【Go】go连接clickhouse使用TCP协议

离开你是傻是对是错 是看破是软弱 这结果是爱是恨或者是什么 如果是种解脱 怎么会还有眷恋在我心窝 那么爱你为什么                      🎵 黄品源/莫文蔚《那么爱你为什么》 package mainimport ("context""fmt""log""time""github.com/ClickHouse/clickhouse-go/v2")func main(

2024.9.8 TCP/IP协议学习笔记

1.所谓的层就是数据交换的深度,电脑点对点就是单层,物理层,加上集线器还是物理层,加上交换机就变成链路层了,有地址表,路由器就到了第三层网络层,每个端口都有一个mac地址 2.A 给 C 发数据包,怎么知道是否要通过路由器转发呢?答案:子网 3.将源 IP 与目的 IP 分别同这个子网掩码进行与运算****,相等则是在一个子网,不相等就是在不同子网 4.A 如何知道,哪个设备是路由器?答案:在 A

图解TCP三次握手|深度解析|为什么是三次

写在前面 这篇文章我们来讲解析 TCP三次握手。 TCP 报文段 传输控制块TCB:存储了每一个连接中的一些重要信息。比如TCP连接表,指向发送和接收缓冲的指针,指向重传队列的指针,当前的发送和接收序列等等。 我们再来看一下TCP报文段的组成结构 TCP 三次握手 过程 假设有一台客户端,B有一台服务器。最初两端的TCP进程都是处于CLOSED关闭状态,客户端A打开链接,服务器端

网络原理之TCP协议(万字详解!!!)

目录 前言 TCP协议段格式 TCP协议相关特性 1.确认应答 2.超时重传 3.连接管理(三次握手、四次挥手) 三次握手(建立TCP连接) 四次挥手(断开连接)  4.滑动窗口 5.流量控制 6.拥塞控制 7.延迟应答 8.捎带应答  9.基于字节流 10.异常情况的处理 小结  前言 在前面,我们已经讲解了有关UDP协议的相关知识,但是在传输层,还有

linux下TCP/IP实现简单聊天程序

可以在同一台电脑上运行,在一个终端上运行服务器端,在一个终端上运行客户端。 服务器端的IP地址要和本地的IP相同,并分配端口号,客户端的默认设置为本地,端口号自动分配。 服务器端: #include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.