-
Notifications
You must be signed in to change notification settings - Fork 0
20210419思考下各个conn的调教方式
form或者to的river中基本上都会包含一个conn,并在内部逻辑轮询,这里首先需要想明白的一个问题是:
一个river内部是只对这个conn进行Read操作,还是只进行write操作,既read又write是被禁止的
read由于最近都在和他打交道,所以思路还算比较明确,那就是river退出只进行跳出轮询循环的操作,以及只析构这个river结构类的内部字段,
而虽然这个conn也是内部字段之一,但是在river内部不该对conn进行任何close操作
而对于write的river,并不需要对其进行轮询,而只是当需要用他来发送数据时,调用一下即可 同样的虽然这个conn也是内部字段之一,但是在river内部不该对conn进行任何close操作
而对于他的上层,也就是TcpServer_6668,我现在所思考的工作内容,打个比方,其实就是关闭网络游戏的服务端(器)
于是思路就变得清晰一些了,因为对于客户端(client)来说,
client都是有能力在服务器的另一端自主关闭conn的;同时server也是有能力关闭某一个,或某几个client的conn,这两个操作其实是同一回事
而server关闭服务端则就是另外一件事了:
本质上是net.Conn.Close()与net.Listen.Close()
net.Conn的Close()流程是这样的:
客户端流程:客户端调用了close(),river内部监测到了异常信号,发送此事件的event给eventbox终端,终端识别后,析构掉所有用到这个conn的river(无论是read还是write),但并不会去专门调用这个conn的close方法,而是一顿析构操作结束后,将conn“放置在一旁即可”
服务端关闭流程:其实不存在服务端关闭某个conn这样的操作,而是只会处于某种原因析构掉某个river或者某几个river:
1.如心跳包无响应超限后,会发送此事件的event给eventbox终端,终端识别后会去析构这个心跳包所在的river
2.如tcpServer6668退出,则会析构掉所有与之相关的river,然后再进行listener.Close()
共同点都是在服务端于不会对某个conn进行直接的close操作,而是让他自动去被内存回收
还是有些问题,conn在被回收前还是有必要执行一次close操作的,否则可能会造成内存泄漏
而目前看来,eventbox的后续逻辑会负责合理的close操作:
最显而易见的逻辑是,如果是心跳包无响应,那只会进行river的注销,而不用去管conn
但是如果监测到客户端那边close()了conn那么除了注销所有与这个conn相关的river之后也要进行conn的合理的close工作
还有如果是主动关闭TcpServer那么就需要先将所有的river注销,在将所有的conn关闭,最后关闭listener,这销毁顺序其实就是方向的创建顺序
在换句话说,服务端严禁在某个river未析构前,关闭他内部所用到的conn,这是最根本原则,客户端的关闭操作不属于这里
客户端的close事件其实是和心跳包异常是一类东西,需要借助eventbox来实现后续逻辑