【网络】运输层协议(二)——UDP及其编程流程

    xiaoxiao2022-07-14  139

    在前两次主要讲述了关于TCP的相关内容,那么在运输层还有一个重要的协议叫做UDP协议。本篇主要来讲解有关于UDP的相关内容。UDP的三个特点是:无连接,不可靠的数据报服务;

    一、UDP协议报文段的首部格式

    用户数据报UDP有两个字段,数据字段和首部字段。首部格式如下图所示,比较简单,只有8个字节,由四个字段组成,每个字段的长度都是两个字节。各个字段的含义如下:

    源端口号:在需要对方回信时选用,不需要时可全用0;

    目的端口号:这在终点交付报文时必须使用;

    报文段长度:UDP用户数据报的长度,其最小值为8.

    校验和:检测UDP报文段在传输中是否出错,出错就舍弃;

    二、UDP的主要特点

    无连接不可靠,即就是UDP尽最大努力交付;数据报UDP没有拥塞控制;UDP支持一对一,一对多,多对一和多对多的交互通讯UDP的首部开销小;

    三、分别介绍UDP的三个特点:无连接的不可靠的数据报服务;

    无连接的:利用UDP进行通讯时,不需要先进行两端的连接。

    不可靠的:UDP是尽最大努力进行数据交付,即不保证可靠的交付。

    UDP的数据报服务:

            发送的次数和接收的次数相等;

            如果接收一次未将数据读取完,则剩余的丢弃

    四、UDP通讯的编程流程——以客户端服务器为例

    (一)服务器:被动通讯方

             Int sockfd = socket(int domain,int type,int protocol);//创建socket

            Int Bind(int sockerfd, const struct sockaddr *addr, socklen_t addrlen);//将服务器的IP地址、端口号与sockfd绑定;

            Int recvfrom(int sockfd, void *buff, int len, int flags, struct sockaddr* destaddr, addrlen_t* len);//必须接受对端地址

            int sendto(int sockfd,void *buff,int len,int flags,struct sockaddr* peeraddr,addrlen_t len);

            Close(sockfd);//直接关闭服务器

    (二)客户端:主动通讯方

            Int sockfd = socket(int domain,int type,int protocol);//创建socket

            (可选)Int Bind(int sockerfd, const struct sockaddr *addr, socklen_t addrlen);//将服务器的IP地址、端口号与sockfd绑定;

            int sendto(int sockfd,void *buff,int len,int flags,struct sockaddr* peeraddr,addrlen_t len);

            Int recvfrom(int sockfd, void *buff, int len, int flags, struct sockaddr* destaddr, addrlen_t* len);//可以不接收对端信息

            Close(sockfd );//直接关闭客户端

    (三)简单代码实现

    /* 服务器端 */ #include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> int main() { int sockfd = socket(AF_INET,SOCK_DGRAM,0); assert(sockfd != -1); //绑定 struct sockaddr_in ser,cli; memset(&ser,0,sizeof(ser)); ser.sin_family = AF_INET; ser.sin_addr.s_addr = inet_addr("127.0.0.1"); ser.sin_port = htons(6500); int res = bind(sockfd,(struct sockaddr*)&ser,sizeof(ser)); assert(res != -1); while(1) { char buff[128] = {0}; int cli_len = sizeof(cli); int n = recvfrom(sockfd,buff,127,0,(struct sockaddr*) &cli,&cli_len); if(n == -1) { close(sockfd); break; } unsigned short cli_port = ntohs(cli.sin_port); char *cli_ip = inet_ntoa(cli.sin_addr); printf("%s:%u %s\n",cli_ip,cli_port,buff); sendto(sockfd,"ok",2,0,(struct sockaddr*)&cli,sizeof(cli)); } close(sockfd); } /* 客户端代码 */ #include<stdio.h> #include<assert.h> #include<string.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> int main() { int sockfd = socket(AF_INET,SOCK_DGRAM,0); assert(sockfd != -1); struct sockaddr_in ser,cli; memset(&ser,0,sizeof(ser)); ser.sin_family = AF_INET; ser.sin_port = htons(6500); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); while(1) { printf("please input data:"); char buff[128] = {0}; fgets(buff,128,stdin); if(strncmp(buff,"end",3) == 0) { close(sockfd); break; } buff[strlen(buff) - 1] = 0; sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&ser, sizeof(ser)); char recvbuff[128] = {0}; int n = recvfrom(sockfd,recvbuff,127,0,NULL,NULL); if(n == -1) { close(sockfd); break; } printf("clien recvfrom data:%s\n",recvbuff); } }

    实现结果:

    两端简单的通讯。

    最新回复(0)