UDP编程及特点

目录

1.UDP编程流程

2.recvfrom()、sento()

3.代码演示

3.udp特点


1.UDP编程流程

socket()用来创建套接字,使用 udp 协议时,选择数据报服务 SOCK_DGRAM。sendto()用来发送数据,由于 UDP 是无连接的,每次发送数据都需要指定对端的地址(IP和端口)。recvfrom()接收数据,每次都需要传给该方法一个地址结构来存放发送端的地址。recvfrom()可以接收所有客户端发送给当前应用程序的数据,并不是只能接收某一个客户端的数据。 

2.recvfrom()、sento()

UDP 数据读写:

recvfrom()读取 sockfd 上的数据, buff 和 len 参数分别指定读缓冲区的位置和大小

ssize_t recvfrom(int sockfd, void *buff, size_t len, int flags.struct sockaddr* src_addr,socklen_t* addrlen);
  • src_addr 记录发送端的 socket 地址
  • addrlen 指定该地址的长度

sendto()往 socket 上写入数据, buff 和 len 参数分别指定写缓冲区的位置和数据长度

ssize_t sendto(int sockfd, void *buff, size_t len, int flags,struct sockaddr* dest_addr,socklen_t addrlen);
  • dest_addr 指定接收数据端的 socket 地址
  • addrlen 指定该地址的长度

3.代码演示

服务器代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	assert(sockfd!=-1);
	
    struct sockaddr_in saddr,caddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
	assert(res!=-1);
	
	while(1)
	{
		int len=sizeof(caddr);
		char buff[128]={0};
		recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
		printf("buff=%s\n",buff);
		sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
	}
	close(sockfd);
	exit(0);
}

客户端代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
	int sockfd=socket(AF_INET,SOCK_DGRAM,0);
	assert(sockfd!=-1);
	
    struct sockaddr_in saddr;
	memset(&saddr,0,sizeof(saddr));
	saddr.sin_family=AF_INET;
	saddr.sin_port=htons(6000);
	saddr.sin_addr.s_addr=inet_addr("127.0.0.1");

	while(1)
	{
		printf("input:\n");
		int len=sizeof(saddr);
		char buff[128]={0};
		fgets(buff,127,stdin);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}

		sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));
		memset(buff,0,128);
		recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
		printf("buff=%s\n",buff);
	}
	close(sockfd);
	exit(0);
}

 运行结果:

3.udp特点

无链接的,不可靠的,数据报服务

1)多个客户端可以同时给服务器发送数据(因为没有建立链接,也就是说服务器没有只和某一个客户端建立链接);

2)服务器关掉再打开是可以接收数据的;(因为没有建立链接)

如果在服务器关闭时发送信息,会阻塞,在服务器再次开机时不会收到这条消息。客户端因为上条消息阻塞,不能再向服务器发送消息。

 3)数据报接收的特点:

用户数据报协议UDP只在IP的数据报服务之上增加了很少一点的功能,这就是复用和分用的功能以及差错检测的功能.

(复用:多个用户使用一个IO资源发送消息;分用:多个用户使用一个IO资源接收消息)

UDP是面向报文的,发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层.UDP对应用层交下来的报文,即不合并,也不拆分,而是保留这些报文的边界.

这就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文,如下图所示.

 在接收方的UDP,对IP层交上来的UDP用户数据报,在去掉首部后就原封不动地交付给上层地应用进程也就是说,UDP一次交付一个完整的报文

因此,应用程序必须选择合适大小的报文.若报文太长,UDP把它交给IP层后,IP层在传送时可能要进行分片,这会降低IP层的效率.反之,若报文太短,UDP把它交给IP层后,会使IP数据报的首部的相对长度太大,这也降低了IP层的效率.

UDP 数据报服务特点:发送端应用程序每执行一次写操作,UDP 模块就将其封装成一个 UDP 数据报发送。接收端必须及时针对每一个 UDP 数据报执行读操作,否则就会丢包。并且,如果用户没有指定足够的应用程序缓冲区来读取 UDP 数据,则UDP 数据将被截断
也就是udp协议sendto和recvfrom的次数是相同的,不会出现沾包;

(TCP:传输控制协议)

对比TCP字节流服务特点:

UDP的其他特点:

(1)UDP没有拥塞控制,因此网络上出现的拥塞不会使源主机的发送速率降低,这对某些实时应用是很重要的.很多的实时应用(如IP电话,实时视频会议等)要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许数据有太大的时延.UDP正好适合这种要求.

虽然某些实时应用需要使用没有拥塞控制的UDP,但当很多的源主机同时都向网络发送高速率的实时视频流时,网络就有可能发生拥塞,结果大家都无法正常接收。因此,不使用拥塞控制功能的 UDP有可能会引起网络产生严重的拥塞问题。

还有一些使用 UDP的实时应用,需要对 UDP的不可靠的传输进行适当的改进,以减少数据的丢失。在这种情况下,应用进程本身可以在不影响应用的实时性的前提下,增加一些提高可靠性的措施,如采用前向纠错或重传已丢失的报文。

(2)UDP支持一对一,一对多,多对一,多对多的交互通信

(3)UDP的首部开销小,只有8个字节,比TCP的20个字节的首部短。

总结UDP主要特点
UDP 是无连接的,即发送数据之前不需要建立连接

UDP 尽最大努力交付,不保证可靠交付,不支持拥塞控制

UDP 面向报文,没有拥塞控制,很适合多媒体通信的要求

UDP 支持一对一,一对多,多对一和多对多的交互通信

UDP 首部开销小,只有8个字节

  • 33
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Linux网络编程(总共41集) 讲解Linux网络编程知识,分以下四个篇章。 Linux网络编程之TCP/IP基础篇 Linux网络编程之socket编程篇 Linux网络编程之进程间通信篇 Linux网络编程之线程篇 Linux网络编程之TCP/IP基础篇 01TCPIP基础(一) ISO/OSI参考模型 TCP/IP四层模型 基本概念(对等通信、封装、分用、端口) 02TCPIP基础(二) 最大传输单元(MTU)/路径MTU 以太网帧格式 ICMP ARP RARP 03TCPIP基础(三) IP数据报格式 网际校验和 路由 04TCPIP基础(四) TCP特点 TCP报文格式 连接建立三次握手 连接终止四次握手 TCP如何保证可靠性 05TCPIP基础(五) 滑动窗口协议 UDP特点 UDP报文格式 Linux网络编程之socket编程篇 06socket编程(一) 什么是socket IPv4套接口地址结构 网络字节序 字节序转换函数 地址转换函数 套接字类型 07socket编程(二) TCP客户/服务器模型 回射客户 /服务器 socket、bind、listen、accept、connect 08socket编程(三) SO_REUSEADDR 处理多客户连接(process-per-conection) 点对点聊天程序实现 09socket编程(四) 流协议与粘包 粘包产生的原因 粘包处理方案 readn writen 回射客户/服务器 10socket编程(五) read、write与recv、send readline实现 用readline实现回射客户/服务器 getsockname、getpeername gethostname、gethostbyname、gethostbyaddr 11socket编程(六) TCP回射客户/服务器 TCP是个流协议 僵进程与SIGCHLD信号 12socket编程(七) TCP 11种状态 连接建立三次握手、连接终止四次握手 TIME_WAIT与SO_REUSEADDR SIGPIPE 13socket编程(八) 五种I/O模型 select 用select改进回射客户端程序 14socket编程(九) select 读、写、异常事件发生条件 用select改进回射服务器程序。 15socket编程(十) 用select改进第八章点对点聊天程序 16socket编程(十一) 套接字I/O超时设置方法 用select实现超时 read_timeout函数封装 write_timeout函数封装 accept_timeout函数封装 connect_timeout函数封装 17socket编程(十二) select限制 poll 18socket编程(十三) epoll使用 epoll与select、poll区别 epoll LT/ET模式 19socket编程(十四) UDP特点 UDP客户/服务基本模型 UDP回射客户/服务器 UDP注意点 20socket编程(十五) udp聊天室实现 21socket编程(十六) UNIX域协议特点 UNIX域地址结构 UNIX域字节流回射客户/服务 UNIX域套接字编程注意点 22socket编程(十七) socketpair sendmsg/recvmsg UNIX域套接字传递描述符字 Linux网络编程之进程间通信篇 23进程间通信介绍(一) 进程同步与进程互斥 进程间通信目的 进程间通信发展 进程间通信分类 进程间共享信息的三种方式 IPC对象的持续性 24进程间通信介绍(二) 死锁 信号量 PV原语 用PV原语解决司机与售票员问题 用PV原语解决民航售票问题 用PV原语解决汽车租赁问题 25System V消息队列(一) 消息队列 IPC对象数据结构 消息队列结构 消息队列在内核中的表示 消息队列函数 26System V消息队列(二) msgsnd函数 msgrcv函数 27System V消息队列(三) 消息队列实现回射客户/服务器 28共享内存介绍 共享内存 共享内存示意图 管道、消息队列与共享内存传递数据对比 mmap函数 munmap函数 msync函数 29System V共享内存 共享内存数据结构 共享内存函数 共享内存示例 30System V信号量(一) 信号量 信号量集结构 信号量集函数 信号量示例 31System V信号量(二) 用信号量实现进程互斥示例 32System V信号量(三) 用信号集解决哲学家就餐问题 33System V共享内存与信号量综合 用信号量解决生产者消费者问题 实现shmfifo 34POSIX消息队列 POSIX消息队列相关函数 POSIX消息队列示例 35POSIX共享内存 POSIX共享内存相关函数 POSIX共享内存示例 Linux网络编程之线程篇 36线程介绍 什么是线程 进程与线程 线程优缺点 线程模型 N:1用户线程模型 1:1核心线程模型 N:M混合线程模型 37POSIX线程(一) POSIX线程库相关函数 用线程实现回射客户/服务器 38POSIX线程(二) 线程属性 线程特定数据 39POSIX信号量与互斥锁 POSIX信号量相关函数 POSIX互斥锁相关函数 生产者消费者问题 自旋锁与读写锁介绍 40POSIX条件变量 条件变量 条件变量函数 条件变量使用规范 使用条件变量解决生产者消费者问题 41一个简单的线程池实现 线程池性能分析 线程池实现 网络编程, Linux

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值