235-Linux udp协议
1.tcp和upd的特点
tcp特点:面向连接、可靠、流式服务
udp特点:无连接、不可靠、数据报服务
2.先运行服务器再启动客户端后,重启服务器,客户端再给服务器发送消息,请问,服务器能收到消息吗?
答案:udp是无连接的,udp的客户端和服务器端是不建立连接的(严格来说udp没有客户端和服务器端),udp的客户端可以直接给服务器发送数据,发送成功就成功了,发送不成功就不成功,没有应答确认、超时重传等机制,应答确认、超时重传等机制是tcp特有的,以此来保证可靠性,但是udp是没有的,相比之下,udp的效率会高一些,tcp牺牲了一些性能来保证可靠性,udp牺牲了可靠性来保证性能,性能高可靠性又高是不存在的
3.假设服务器每次只recv一个字符,那么客户端第一次发送hello,服务器就只收到h,第二次发送abc,服务器就只收到a,第三次发送123,服务器就只收到1,后面的数据都哪里去了?
答案:丢了,读不到了
tcp流式服务不会丢失数据,无论服务器是接收一次还是几次,肯定都能够收到,而udp数据包服务可能会丢失数据,udp不会出现将两次发送的数据合并到一块发给服务器,不存在粘包这个问题,所以udp要求接收方一次能够将数据全部收走,否则就会丢失数据
4.tcp流式服务和udp数据报服务
对于tcp发送端的TCP发送缓冲区,它不知道helloabcdtest是通过一次send传进来的,还是两次,十次,不知道也不关心,对于接受端的TCP接收缓冲区,它也不知道里面的helloabcdtest是通过一个TCP报文段传进来的,还是两个,十个,不知道也不关心,只关心一点recv的时候TCP接收缓冲区中的数据少于recv一次接收的数据,就一次都接受,否则就分开就收就完了,总之接受完就ok
udp数据包传送的时候可能会丢失,丢了就丢了,不关心,一般情况下也不会丢,只是有可能会丢
tcp和udp在传输层,ip在网络层,ip也是不可靠的,那么tcp也是需要通过ip来传送数据,那么tcp怎么保证可靠性?
答案:tcp的可靠是tcp协议自己来实现的,tcp协议自己有应答确认、超时重传的机制
5.如何实现让udp也可靠呢?
答案:可以在一定程度上模拟tcp在应用层的实现
比如服务器收到数据了以后,要给客户端一个回复告诉客户端收到了数据,客户端就把数据丢掉了,在服务器没有给客户端回复之前,客户端都保留着数据,要是客户端等了好长时间服务器都没有告诉客户端服务器收到了,客户端就在重发一次等等
6.udp服务器代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.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,1,0,(struct sockaddr*)&caddr,&len);
printf("buff=%s\n",buff);
sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
}
7.udp客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.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)
{
char buff[128] = {0};
printf("input\n");
fgets(buff,128,stdin);
if(strncmp(buff,"end",3) == 0)
{
break;
}
sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,sizeof(buff));
int len = sizeof(saddr);
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
printf("buff=%s\n",buff);
}
}
8.如果tcp使用了6000这个端口,那么udp还能使用6000这个端口吗?
答案:tcp可以和udp同时使用相同的端口号
一个端口只能被一个进程来使用,但是tcp和udp是两个不同的协议,相互之间不影响
通过netstat命令可以看到tcp和udp确实是可以同时使用6000号端口的
注意:udp是没有状态的
9.一个进程可以同时创建多个监听套接字(比如tcp、tcp或者tcp、udp或者更多个套接字)吗?
答案:可以的,一个进程既有可能是服务器也有可能是客户端,当然使用的端口号肯定是不致的,一个进程可以有多个监听套接字和多个连接套接字,无论是tcp还是udp都是可以的
10.什么场景下使用tcp,什么时候使用udp?
答案:udp:实时性高、高速传输的场景,tcp:可靠性高的场景
udp性能好,开销小,传输速度快,适用于IP电话,直播,视频会议等高速传输的场景,udp可靠性低,可能会出现丢包的问题,只是卡了一下,但是对它们的影响很小
tcp可靠性高,适用于文件传输等对可靠性要求较高而对传输速度要求没那么高的场景
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfcbif
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01