服务器的网络收发

 

一直以来都没怎么写过什么东西,主要是每次准备动手的时候,突然发觉自己词汇很贫乏,什么都写不出来,连列个1、2、3、4给自己整理个思路都难。虽然如此,可是也很羡慕别人在网上发布的文章,也一直想写,不管水平怎么样,把自己的经历写下来,让自己看也好。长时间没有登录csdn了,今天心血来潮登录上来看看,也就随便写点什么吧。

   以前工作的时候,都是急急忙忙的实现功能了事,没人要求考虑写出来的代码的效率,自己对自己的要求也就降低了。最近赶鸭子上架,要设计实现一个消息通讯的服务器。虽然领导的需求还是三天一变,也从没在他嘴里听到过什么性能需求,但是不想任由自己这么下去,就有了下面的这段经历。

   要实现的服务器要求和其它多个客户端或其它服务器进行消息交换(数量不定,领导没给个概数),TCP和UDP都要用到。消息通讯的通讯服务器,我个人认为性能最大瓶颈应该就是接收和发送这一块。这一块的实现,经历了三个阶段。

我刚接手的时候,接收模块,使用一个线程来阻塞调用recvfrom接收UDP数据,一个线程来listen 并accept,每成功返回,就创建一个线程去recv。每个线程接收到的数据都自己去处理。发送模块只有一个线程,从队列里取出待发送的数据,判断使用的协议,如果是UDP,就直接sendto,如果输TCP,就根据目的地,查找连接,如果没有,就先connect然后再send。这种实现方式,怎么看都觉得别扭,当时建议领导重新设计这一块,但领导不同意,领导要的是一个能基本实现所有功能的东西,只能先实现其它模块去了。可悲领导的需求真的是三天一变,每想到一个主意,就要求去实现,可每次基本完成让领导看的时候,这需求有变了

。那时是我最烦燥的一段时间,所以没有放任何心思在收发部分上。

程序刚能运行起来的时候,试了一下,发现效率奇差,把结果报给领导,领导很惊讶:“怎么会那么差?那样不行,改改吧!”。当时仍然很烦燥,基本是领导要求做什么就做什么,很少动心思。领导随口一句,用线程池,于是就用线程池。稍微改改后,就变成了这样:发送那块基本不变,接收那块,UDP线程接收数据后,不再进行处理,直接放进一个接收队列。TCP呢,当时认为接收数据只是从socket的接收缓冲区里把数据拷出来而已,就改为使用一个线程,使用epoll触发所有socket,如果是listen的,就accept,其它的就recv出来放到接收对了里。然后使用一个简单的线程池模型去从队列里去消息出来进行处理。

后来心态有所变化,心中的愤懑消失了,觉得毕竟对自己是个锻炼,决定私下修改这两部分,于是就变成了这样:把接收对了改成了任务队列,在接收端,接收UDP数据的那个线程基本没有什么变化,就是接收到消息之后,封装成一个消息处理任务再放到队列里。TCP仍然是使用单线程和epoll,但不再负责accept和recv,而是把触发事件的socket封装成accept任务和recv任务放到任务队列里。发送模块,为UDP数据创建一个队列,使用单独一个线程不断冲队列中取消息并sendto,同时为每个方向的TCP连接也创建一个队列,然后使用一个线程来轮询所有方向的连接,如果连接失效,就生成一个connect任务放到任务队列,同时使用另一个epoll,对于有待发送数据的连接,就加入epoll的触发列表中。对于每个触发了可写事件的socket,再生成send任务,放到任务队列。同时保留那个线程池,不断从任务队列中取出任务进行处理。

这个就是目前的版本了,还没有经过测试,不知道结果怎么样。不过又发现了新的问题。服务器维护一颗树,部分消息需要查询这个树,决定转发的方向,部分消息会对这颗树进行修改,这颗树需要持久保持,当然,这颗树的规模,领导同样没有给出。由于使用线程池对消息进行处理,就有涉及到同步的问题。不想对这颗树加一个大锁,那样子使用线程池处理消息的效率还不如不如使用单线程。这两天先查资料考虑这个问题,如果有时间,就再把结果发上来。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值