UDP编程应用探讨一

由于在项目中用TCP比较多,也发现TCP在频繁数据传输的应用中存在拥塞的缺点。考虑到UDP在这方面存在优点,抽出时间专门测试一下UDP的编程使用和TCP的区别,以使下次设计应用层协议时正确选择传输层协议


1、 UDP每次操作都是针对一个数据包,而TCP操作数据流

发送方调用3sendto 发送大小都为64B 的数据包:

数据包Aa_HelloWorld

数据包Bb_HelloWorld

数据包Cc_HelloWorld

 

情况一

接收方调用2recvfrom 

接收长度参数为4时:

1次,接收到数据包Aa_He

2次,接收到数据包Bb_He

 

情况二

接收方调用3recvfrom

接收长度参数为1024

1次,接收到数据包Aa_HelloWorld

2次,接收到数据包Bb_HelloWorld

3次,接收到数据包Cc_HelloWorld

 

上述两种情况与TCP有很大区别,

第一种情况,若是TCP调用2recv,接收大小为4

将会接收到“a_HelloW”,剩下的数据将留着socket的接收缓存中

而在UDP中,仅数据包C留着socket接收缓存中

 

第二种情况,若是TCP调用3recv,接收大小为1024

仅第1次即会把3个数据包接收完,第23次调用都不会接收到数据(阻塞或接收0个)。

 

2、 发送速率 大于 接收速率

发送端每1s调用sendto发送数据包A到接收端,而接收端每3秒调用recvfrom接收数据包A。此时当接收缓存满时,接收端将出现掉包的情况。但发送端和接收端都是不知道丢包发生了的。

 

3、 UDP协议中有校验和(2B

用于增加传输的可靠性,校验和不对将丢包(并不重传)



//接收端源文件
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<netinet/in.h>
#include<sys/socket.h>

int main(void)
{
	int rsck = socket(AF_INET, SOCK_DGRAM, 0);
	if(rsck < 0)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in r_addr, s_addr;
	int r_len = sizeof(r_addr);
	int s_len = sizeof(s_addr);
	bzero(&r_addr, r_len);
	r_addr.sin_family = AF_INET;
	r_addr.sin_port = htons(5678);
	r_addr.sin_addr.s_addr = INADDR_ANY;//inet_addr("192.168.1.124");

	int sinsize = 1;
	setsockopt(rsck, SOL_SOCKET, SO_REUSEADDR, &sinsize, sizeof(int));
	int ret = bind(rsck, (struct sockaddr*)&r_addr, r_len);
	if(ret < 0)
	{
//		fprintf(stdout, "bind receive socket fail : %s\n", errorn);
		perror("bind");
	}
	char rbuf[1024];
	while(1)
	{
		usleep(10000);
		ret = recvfrom(rsck, rbuf, 5, 0, (struct sockaddr*)&s_addr, &s_len);
		printf("%d:%s\n", ret,rbuf);
	}
	char sbuf[64] = "nice!!";
	sendto(rsck, sbuf, sizeof(sbuf), 0, (struct sockaddr*)&s_addr, s_len);
	close(rsck);
	return 0;
}

//发送端源文件
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>

int main(void)
{
	int ssck = socket(AF_INET, SOCK_DGRAM, 0);
	if(ssck < 0)
	{
		perror("socket");
		return -1;
	}
	struct sockaddr_in dest_addr, src_addr;
	int dest_len = sizeof(dest_addr);
	int src_len = sizeof(src_addr);
	bzero(&dest_addr, sizeof(dest_addr));
	dest_addr.sin_family = AF_INET;
	dest_addr.sin_port = htons(5678);
	dest_addr.sin_addr.s_addr = inet_addr("192.168.188.229");
	char sbuf[64] = "Hello, i am send";
	int i=0;
	char tmp[16];
	while(1)
	{
		sprintf(tmp, "[%d]", i++);
		strncpy(sbuf, "Hello, i am send", 64);
		strncat(sbuf, tmp, 64);
		//sleep(1);
		int slen = sendto(ssck, sbuf, sizeof(sbuf), 0, \
		(struct sockaddr*)&dest_addr,dest_len);
		printf("slen = %d , chars : %s\n", slen, sbuf);
	}
	recvfrom(ssck, sbuf, sizeof(sbuf), 0, (struct sockaddr*)&src_addr,		&src_len);
	printf("%s\n", sbuf);
	close(ssck);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值