2020/01/14 02-群聊UDP服务端客户端实现和心跳机制

在这里插入图片描述
TCP编程和UDP编程,套路不一样,
UDP是无连接协议,不用关心,发数据的对端是否存在,数据发出去即可,编程模型比较简单,作为服务器端一般是要固定在一个端口上,,这样别人才能连接到,UDP和TCP的服务都需要一个端口绑定

TCP要多一个listen监听端口,UDP绑定之后直接就可以了
下面就是收发的过程:
TCP比较麻烦,每链接一次,就要借助一个ACCEPT,链接成功后,建立一个有链接的链接通道。
TCP每开一个链接就会创建一个新的socket。建立连接后,TCP就可以通过新的socket通讯,
UDP不需要维护一个链接,不需要新的socket(用同一个socket来回收发数据,开几个socket,关几个socket)

scocket内部维护了一些数据,laddr本地,raddr远程,从A发到B,就需要自己有个端口才能向对方发数据,没有端口是不能发送数据的,首先要在某个协议上占一个端口,然后才能发送数据,对端的地址和端口也需要知道,一个数据包必须有源IP和目标IP用来做路由,应用层就需要知道端口,否则不能在应用层进行通讯
TCP协议知道两端IP和端口,
UDP是不知道的,
bind是给自己的应用程序绑定地址和端口
connect链接,填写两个值,本地laddr,raddr、
sendto,会把自己地址端口填充,远端不记住
send,(如果前面没有laddr,连这个都过不了)自己没绑定laddr是发送不出去数据的
recv 一定要有本地端口laddr

在这里插入图片描述
UDP多个客户端现在来通讯没什么问题
初始化后,就可以进行bind绑定,阻塞开启一个线程recv
等待客户端发来数据,每发来数据,就认为是跟自己链接的客户端,用set把客户端记录,然后去重(因为客户端重复发送数据,每次记录不合适)
在这里插入图片描述
记录地址后,遍历地址发送消息,但是不保证对方能收到在这里插入图片描述
如果友好一点,客户端主动告诉下线了,这里加个判断,然后remove元素,(元素就是raddr)不能break,因为还是这个socket在使用,只能continue
当对方发主动退出信息,就把对方从set中remove
在这里插入图片描述
TCP需要加锁,每一个socket recv扔到一个线程中执行,在其他线程群发的时候,另一个线程可能就退出了,这时候就会出现问题,因为同一个字典要变化长度,正在遍历就不允许,所以要加锁
UDP不管连接几个客户端。,都是一个线程,所以客户端都在一个线程里操作,除了主线程,其他只有一个recv线程,不需要加锁

在这里插入图片描述
如果调皮,进来每直接给信息,直接quit,在set里就找不到raddr
在这里插入图片描述
做一个keyerror判断即可在这里插入图片描述
写一个客户端,connect就知道对端地址,stop清理资源
在这里插入图片描述
还需要造一个send方法发送数据。,凑个时间发送过去在这里插入图片描述
recv和recv from别人也是可以给你发送消息的,对客户端来讲要临时占用端口在这里插入图片描述
recv阻塞的较多,还是开启线程,connect之后,laddr和raddr都有,下面开启recv线程,阻塞在等待别人发送消息在这里插入图片描述在这里插入图片描述
TCP是要建立链接才能发送数据,但是UDP可以不这么做

先启动一个server
在这里插入图片描述在这里插入图片描述
准备和客户端开始连接
在这里插入图片描述
收到了在这里插入图片描述
现在laddr是58122
在这里插入图片描述
发送一个hello ack在这里插入图片描述
这里就收到了
在这里插入图片描述
使用自己的server端代码试试,现在有两个线程
在这里插入图片描述
客户端起来先发个hello在这里插入图片描述
服务器收到消息就回复了在这里插入图片描述
客户端再发送消息
在这里插入图片描述
服务器端收到了
在这里插入图片描述
再启动一个客户端,发送22222在这里插入图片描述
新起来的客户端在51165上在这里插入图片描述
发送quit
在这里插入图片描述
服务器端没有写接收quit的回应消息,但是确实退出了
测试
下次作为类,这一段代码导入的时候就不执行,测试代码都这么写在这里插入图片描述在这里插入图片描述

服务器端加个输出信息
运行服务器端,在这里插入图片描述
运行客户端在这里插入图片描述
客户端发送消息,都分别受到了信息在这里插入图片描述
这样是同一个进程跑两个客户端对象在这里插入图片描述
这样run是两个进程,两个进程两个客户端在这里插入图片描述
右键运行客户端要理解,是一个进程多个线程还是多个进程多个线程,socket如何去跑的是要清楚的

现在不给数据就是永久阻塞,一个是悄悄给自己发一个,第二种是变成非阻塞,但是代码就不是这么写了
在这里插入图片描述
一般不会用socket来写,因为太底层了,后面开发用高级库了在这里插入图片描述
在这里插入图片描述
遗留了问题,友好告诉服务器端quit,(TCP要是断了链接就可以感觉到,是协议保证的),UDP是一种无连接协议,必须要一种机制知道谁下线了,心跳机制

在这里插入图片描述
心跳机制只是发个包过去,还有ACK机制(响应机制),心跳是定时发的包,从一端发往另外一端,心跳包没有大的,都是很小的,能少一个字节就是一个字节,间隔看具体情况,你能容忍多久不在线合适
ACK,一端收到另一端消息,回复收到了(TCP和UDP都用,)
(TCP链接有个通病,长时间不管,隔一段时间就不工作了,想用这个链接就不能工作了,保持活性,就发心跳包)

心跳机制:
1.客户端定时向服务器发,服务器可以ack,也可以不ack(大部分采用)
2.服务器定时向客户端发,客户端一般需要ack,如果没有ack,就认为掉线了,(ack需要一个次数,比如5次)使用比较少
3.可以双向发心跳包,使用很少

在这里插入图片描述
采用第一种心跳机制改进代码
在这里插入图片描述
现在定义一个服务端收到心跳包的代码在这里插入图片描述
需要记录时间
在这里插入图片描述
现在收到一个心跳包,包来了记录一下直接跳过,记录最后一次与服务器连接时间,在这里插入图片描述
假如没有发心跳包,设定间隔时间
在这里插入图片描述
假如有2W个客户端,只有2个下线了,聊天工具往往是一个慢的程序,不是一个高效的网络传输程序,
懒的策略是,在发送的时候,顺道遍历的过程中把已经超时的清理掉。
所以准备在当前线程中,发送消息的时候,顺带把超时的清理掉

raddr是key,ts是时间戳,当前时间-时间戳(时间戳是从unix元年1970年开始)=浮点数>阈值
大于时间阈值
在这里插入图片描述
大于就等于对方下线了,下面遍历把超时的踢出去即可
在这里插入图片描述
客户端一开始就发了心跳包,这样一开始记录的是通讯时间,说明这个客户端活着在这里插入图片描述
服务器端代码主要是在recv解决
在这里插入图片描述在这里插入图片描述
服务器代码运行
在这里插入图片描述在这里插入图片描述
消息是从端口10000发来的
在这里插入图片描述
敲一个回车,只剩10001
在这里插入图片描述
10000的记录就被清除了在这里插入图片描述
发心跳包的目的就是,维护一个客户端有效的列表

现在开始客户端

客户端一旦工作,就需要向服务器端汇报,也是起线程
在这里插入图片描述
现在要完成这个heartbeat函数
在这里插入图片描述
主线程退出,心跳包也退出,daemon,recv的话需要等别人返回所以none-daemon比较好在这里插入图片描述
客户端发送心跳,服务端只是记录列表,没有ack,没有alive的就被删除在这里插入图片描述
加心跳需要记录,把原来的set,变成字典,用字典来记录每一个客户端,最后一次发数据的时间,记录这个时间,
最后和当前时间的差和阈值做比较
在这里插入图片描述
心跳一般都是daemon
在这里插入图片描述
主动退出
在这里插入图片描述
在这里插入图片描述
有链接TCP,无连接udp,
UDP设计的时候是基于,网络好,消息不丢包,包没乱序,
但是在广域网的情况下,这个情况就有一些问题了,丢包可能比较严重
就可以在应用层的时候,校验一下,发送的数据是否正确,CRC校验,奇偶校验
UDP应用就可以用视频,音频

有些传感器是微秒级的传输数据,比如桥梁震动,UDP协议来传输就比较好

DNS协议,把域名转换成IP地址,DNS协议用UDP协议访问,53端口,你发送的包和回来的包,都是一个包,不会乱序的问题,就采用了UDP,发过去丢了,再发即可
在这里插入图片描述
UDP性能优于TCP,可靠性高的还需要选择TCP
在这里插入图片描述
TCP和UDP,面试问该怎么用?
UDP在局域网用的时候问题不大,但是有些问题,效率高,但是有可能丢包,乱序,对方挂了也不知道,如果在这种情况下,要保证数据可靠性就可以用TCP
TCP有链接协议,但是成本比较高,(可以尽量维持这个链接,使用心跳)

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值