失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 网络编程传输层——UDP通信

网络编程传输层——UDP通信

时间:2020-04-26 11:53:37

相关推荐

网络编程传输层——UDP通信

何为传输层?

在物理层、数据链路层、网络层解决了主机和主机之间能够发送接收数据,但是在计算机网络中,主机的通信主体还是进程,而传输层则解决应用进程的通信,所谓传输层协议也是端对端协议

传输层的协议主要有两种:TCP协议UDP协议

本章这次主要是针对的UDP协议,下一章才是针对TCP协议的具体理解。

在传输层需要了解到一个新的概念:端口号port(可以理解为你要从那个地方传进去),设计了一个端口号来标识主机中的进行网络通信的进程。

port:16bit整形(两个字节)

端口号只在本机上有作用,在不同主句中同一个程序执行,也可以用不同的端口号。

什么是UDP协议?

UDP协议(用户数据报协议)(非面向连接)

1. 无连接,不需要提前把两个程序关联起来(想发给谁就发给谁)。

2. 面向报文的传输,应用程序要发送的数据,直接封装在udp数据报中(直接放在udp协议内容 后),既不做拆分也不做合并,直接交给网络层。

3. 不可靠,不保证数据一定能到达,尽最大努力交付。

UDP协议就是在MAC帧的外面在加上一层传输协议,既加上UDP头部,它的头部由以下四部分组成。

源端口:自己主机的端口号

目标端口:要传到那个主机的端口号

下面这张图是一个传输模型

可以看出这是TCP/IP网络模型,因为只有四层,从用户层、传输层、网络层、网络接口层构成。

在操作系统当中,其实网络协议是有写好了的函数库可以使用,只需要选择对应的协议就行。

如何进行UDP协议进行通信?

1、首先我们需要了解udp怎样进行通信的,下图是udp通信流程

清楚了流程,但肯定不懂得后面函数得意义吧,下面来进行函数的细讲:

1、创建套接字(这里就是相当于创建一个包含网络通信协议的套接字文件)

#include <sys/types.h>#include <sys/socket.h>int socket(int somain, int type, int protocol);参数1:选择那种ip地址进行通信-----网络层 AF_INET IPV4参数2:选择那种传输-----传输层 SOCK_STREAM TCP SOCK_DGRAM UDP SOCK_RAM 不使用参数3:套接字协议 0 默认返回值 成功:返回套接字 失败:返回-1

2、绑定套接字(也就是将自己的本地网络信息绑定到网络协议中)

#include <sys/types.h> /* See NOTES */ #include <sys/socket.h>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)参数1;利用函数int socket函数创建的套接字参数2:自己的IPV4网络信息struct sockaddr_in { sa_family_t sin_family; 地址族:AF_INET/*address family: AF_INET */ in_port_t sin_port;port端口号:当前进程的端口号 struct in_addr sin_addr;ip地址:本地网络地址 /* internet address */ };struct in_addr { uint32_t s_addr;32位整数,ip地址 /* address in network byte order */ };参数3:结构体大小,直接sizeof(struct addr)

3、这个函数就是发送数据与接收数据(发给谁,接收谁)

UDP发送数据ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);参数1:要通过套接字发送给谁参数2:要发送数据的首地址参数3:发送数据的大小参数4:标志 0:阻塞等待,发送完成才结束参数5:const struct sockaddr *dest_addr:结构体地址,要包含目标,接收方的地址、端口参数6::结构体大小,目标网络信息结构体的大小返回值 成功:返回发送的字节数 失败:返回-1UDP接收数据ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);参数1:int sockfd:套接字,本地套接字携带了本地的网络信息,进行匹配 参数2:void *buf:接收了数据存储的地址 参数3:size_t len:最大接收多少个字节 参数4:int flags:标志 0:阻塞接收,函数一直等待接收了数据,完成接收才结束 参数5:struct sockaddr *src_addr:结构体地址,把发送方的ip、port存储到这个结构 体,得到发送方的信息 如果不需要 填NULL 参数6:socklen_t *addrlen:把结构体大小也存储到这个地址,得到发送方对应的信息大小 如果不需要 填NULL 返回值: 成功:返回接收到的字节数失败:返回-1

在计算机存储数据中,有大小端之分(大端(高存低地址,低存高地址)小端(高存高地址,低存低地址)),但是在网络上传输时,统一成了大端模式。

在网络上传输的方式是网络字节序,而在机器上存储的方式是主机字节序。

则我们需要在传输时将主机字节序转网络字节序 ,网络字节序转主机字节序。

实例:

发送端程序:

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <unistd.h>//当前进程发送数据到指定主机的指定进程中,然后接收对方的数据int main(){//1、创建套接字------在进程中要使用网络通信协议,得到套接字文件描述符int sockfd = socket(AF_INET,SOCK_DGRAM,0); //IPV4,UDP协议//2、绑定套接字,绑定套接字 中 协议中本地的网络信息//把套接字,绑定本地网络信息struct sockaddr_in srcaddr;//本地网络信息---源信息srcaddr.sin_family = AF_INET;//ipv4 地址srcaddr.sin_port = htons(9999);//当前进程的端口号srcaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");//把主机地址转为32位整数bind(sockfd,(struct sockaddr *)&srcaddr,sizeof(struct sockaddr_in));//3、发送数据//目标结构体struct sockaddr_in destaddr;//目标信息destaddr.sin_family = AF_INET;destaddr.sin_port = htons(8888);destaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");while(1){char buf[20],buf2[20];scanf("%s",buf);//输入了数据sendto(sockfd,buf,20,0,(struct sockaddr *)&destaddr,sizeof(destaddr));发送recvfrom(sockfd,buf2,20,0,NULL,NULL);接收printf("%s\n",buf2);}close(sockfd);}

接收数据程序、

#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdio.h>#include <unistd.h>//当前进程接收数据,然后发送给对方int main(){//1、创建套接字------在进程中要使用网络通信协议,得到套接字文件描述符int sockfd = socket(AF_INET,SOCK_DGRAM,0);//2、绑定套接字,绑定套接字 中 协议中本地的网络信息//把套接字,绑定本地网络信息struct sockaddr_in srcaddr;//本地网络信息---源信息srcaddr.sin_family = AF_INET;//ipv4 地址srcaddr.sin_port = htons(8888);//当前进程的端口号srcaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");//把主机地址转为32位整数bind(sockfd,(struct sockaddr *)&srcaddr,sizeof(struct sockaddr_in));//3、接收数据//目标结构体struct sockaddr_in destaddr;//目标信息destaddr.sin_family = AF_INET;destaddr.sin_port = htons(9999);destaddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");char buf2[20];while(1){recvfrom(sockfd,buf2,20,0,NULL,NULL); //接收printf("%s\n",buf2);sendto(sockfd,buf2,20,0,(struct sockaddr *)&destaddr,sizeof(destaddr)); //发送获取}close(sockfd);}

UDP协议采用的非面向连接(没有连接),所以还是有很多问题的,无连接、不可靠、面向数据报的传输 。而且发送了也不知道发送到了没,缺点之一。

如果觉得《网络编程传输层——UDP通信》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。