再来说说TCP和UDP

之前我们介绍过一次TCP和UDP的区别以及各自的优缺点,但是总感觉写得不太细致,仍有许多有待补充。因此,今天就来再归档一次。
在这里插入图片描述

UDP

UDP也叫做用户数据报,是不需要建立连接的协议,它的作用就是将需要进行网络传输的数据压成二进制的格式,再进行传输。 暴力是它典型的特点。 因为它减少了一些保证数据可靠的机制,比如数据包分组、排序,直接将每份消息段放在队列中,应用程序就会每次从这个队列读取。因此,减少了这些繁琐的步骤,它的速度也就哗啦啦上来了。在这里,它的传输速度只受传输的带宽、计算机的能力、数据生成的速度所影响。
也因为缺少了类似TCP这样繁琐的机制,UDP可以被攻击的漏洞也就少了一些。但这也是要付出代价的,就是失去了数据传输的可靠性,也就是我们无法得知传输的数据是否完整地、安全地到达对方。

优缺点:速度快并较为安全但是可靠性差。由于UDP的控制选项较少、在数据传输的过程的延迟小,就适合对可靠性要求不高的应用程序,比如视频、音频的传输。
建立流程以及代码实现:

UDP编程的服务器实现步骤:

1.使用socket()创建一个socket(SOCK_DGRAM);
2.设置socket的属性;
3.使用bind()绑定IP地址和端口地址到socket上;
4.使用recvform()循环接收数据;
5.关闭连接

服务端代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
	int n;
	char recvline[1024] = {0};

	int sockfd;
	struct sockaddr_in servaddr;

	/* 创建一个UDP连接的socket */
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

	/* 变量servaddr清零 */
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);	
	servaddr.sin_port = htons(50001);

	/* 绑定servaddr到创建的socket上 */
	bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	/* 接收客户端发送的数据 */
	recvfrom(sockfd, recvline, 1024, 0, NULL, NULL);

	printf("%s\n", recvline);

	/* 关闭socket连接 */
	close(sockfd);
}

UDP编程的客户端实现步骤:

1.使用socket()创建一个socket;
2.设置socket的属性;
3.使用bind()设置对方的IP地址和端口地址到socket上;
4.使用sendto()循环发送数据;
5.关闭连接

客户端代码:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
	int sockfd;
	struct sockaddr_in servaddr;

	if(argc != 2)
	{
			printf("usgae: ./client [ip]\n");

			return -1;
	}

	/* 创建一个UDP的socket连接 */
	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

	/* 变量servaddr清零 */
	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(50001);
	servaddr.sin_addr.s_addr = inet_addr(argv[1]);

	char sendline[100];
	sprintf(sendline, "Hello, world!");

	/*  发送数据 */
	sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

	/* 关闭socket连接 */
	close(sockfd);

	return 1;
}

TCP

TCP也叫做传输控制协议。在进行TCP传输交换前,必须在客户端和服务端都建立起一个连接。它是将数据流分割成若干长度的报文段之后进行传输的连接。

如何保证传输过程中的可靠性?

1.当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。当TCP收到发自TCP连接另一端的数据,它将发送一个确认。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。

2.TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(希望发端超时并重发)

3.既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。

4.TCP的接收端必须丢弃重复的数据

5.缓冲区控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓冲区溢出。

优缺点:因为TCP在传输前必须建立连接,因此这不仅消耗时间也消耗资源,并且在数据传输时的机制三次握手、重传、拥塞控制、四次挥手这些都会消耗大量时间。和UDP一样,保证安全也是需要付出代价的,那就是因可攻击的点太多了,所以TCP更加容易受到攻击。当我们需要保证数据稳定地传输到对方那时,就得使用TCP,比如我们日常用的HTTP、SMTP、FTP都是使用TCP。
建立流程以及代码实现:

TCP编程的服务器端实现步骤:

1、使用socket()函数创建一个socket(SOCK_STREAM);
2、使用函数setsockopt()设置socket属性;
3、使用bind函数()绑定IP地址、端口等信息到socket上;
4、使用用函数listen()开启监听;   
5、接收来自客户端上来的连接,使用用函数accept();
6、用函数send()和recv(),或者read()和write()进行收发数据;   
7、关闭网络连接; 
8、关闭监听;

服务端代码:

#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main()
{
	int sfp, nfp, num = 0;
	struct sockaddr_in s_add,c_add;
	int sin_size;
	unsigned short portnum=0x8888;

	char buffer[100] = {0};

	printf("Hello,welcome to my server !\r\n");

	sfp = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == sfp)
	{
			printf("socket fail ! \r\n");
			return -1;
	}

	printf("socket ok !\r\n");

	bzero(&s_add,sizeof(struct sockaddr_in));
	s_add.sin_family=AF_INET;
	s_add.sin_addr.s_addr=htonl(INADDR_ANY);
	s_add.sin_port=htons(portnum);

	if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
	{
			printf("bind fail !\r\n");
			return -1;
	}

	printf("bind ok !\r\n");

	if(-1 == listen(sfp,5))
	{
			printf("listen fail !\r\n");
			return -1;
	}

	printf("listen ok\r\n");



			sin_size = sizeof(struct sockaddr_in);

			nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
			if(-1 == nfp)
			{
					printf("accept fail !\r\n");
					return -1;
			}

			printf("accept ok!\r\nServer start get connect from %#x : %#x\r\n", 
									ntohl(c_add.sin_addr.s_addr), ntohs(c_add.sin_port));
			while(1)
			{
					memset(buffer, 0, 100);
					sprintf(buffer, "hello,welcome to my server(%d) \r\n", num++);
					send(nfp, buffer, strlen(buffer), 0);
					usleep(500000);
			}


			close(nfp);


	close(sfp);

	return 0;
}

TCP编程的客户端实现步骤:

1、使用socket()函数创建一个socket(SOCK_STREAM);
2、使用函数setsockopt()设置socket属性;
3、使用bind函数()绑定IP地址、端口等信息到socket上;
4、连接对方的IP地址以及端口号;   
5、使用connect()连接服务器;
6、用函数send()和recv(),或者read()和write()进行收发数据;   
7、关闭网络连接;

客户端代码:

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(int argc, char **argv)
{
	int cfd;
	int recbyte;
	int sin_size;
	char buffer[1024] = {0};

	struct sockaddr_in s_add, c_add;
	unsigned short portnum = 0x8888;

	printf("Hello,welcome to client!\r\n");

	if(argc != 2)
	{
			printf("usage: echo ip\n");
			return -1;
	}

	cfd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == cfd)
	{
			printf("socket fail ! \r\n");
			return -1;
	}

	printf("socket ok !\r\n");

	bzero(&s_add,sizeof(struct sockaddr_in));
	s_add.sin_family=AF_INET;
	s_add.sin_addr.s_addr= inet_addr(argv[1]);
	s_add.sin_port=htons(portnum);
	printf("s_addr = %#x ,port : %#x\r\n",s_add.sin_addr.s_addr,s_add.sin_port);

	if(-1 == connect(cfd,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
	{
			printf("connect fail !\r\n");
			return -1;
	}

	printf("connect ok !\r\n");

	while(1)
	{
			if(-1 == (recbyte = read(cfd, buffer, 1024)))
			{
					printf("read data fail !\r\n");
					return -1;
			}

			printf("read ok\r\nREC:\r\n");
			buffer[recbyte]='\0';
			printf("%s\r\n",buffer);
	}

	close(cfd);

	return 0;

}
小结如下
  • TCP是面向连接、可靠、有序的连接,而UDP则是无连接、不可靠、无序的连接。 UDP速度较快而TCP速度较慢。
  • 因TCP的保证可靠、有序的机制存在,它开销较大,在TCP头部需要20字节而UDP头部仅需要8个字节。
  • TCP是通过字节流传输的,因此TCP无界,而UDP因为每一个包都是单独的,所以UDP有界。
  • TCP有拥塞控制,主要靠三次握手、慢开始、快重传、快恢复、拥塞避免实现,而UDP没有
  • 基于TCP的协议有:HTTP/HTTPS、Telnet、FTP、SMTP。
  • 基于UDP的协议有:DHCP、DNS、SNMP、TFTP、BOOTP。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值