忘记密码   免费注册 查看新帖 | 论坛精华区

ChinaUnix.net

  平台 论坛 博客 认证专区 大话IT 视频 徽章 文库 沙龙 自测 下载 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
楼主: duanjigang

谈谈你接触的通讯程序的模型 [复制链接]

论坛徽章:
0
发表于 2011-01-05 18:08 |显示全部楼层
说的很好,一个很实用的话题,谢谢这些无私的朋友!

论坛徽章:
0
发表于 2011-01-06 09:34 |显示全部楼层
本帖最后由 duanjigang 于 2011-01-06 09:50 编辑

呵呵,感冒耽搁了几天,今天把使用ICE中间件的这种方式补充上来:wink:

第三种方式,结合ICE中间件进行设计。
ICE提供了一个多系统,多语言互通的中间件,通过使用slice语言定义一个.ice文件来实现不同程序的通讯数据结构和调用方法的定义。
然后调用slice2XX(xx=cpp,java,php..)来生成对语言的代码。对于开发人员来说,只需要把生成的java或者cpp代码包含到自己的工程中来,客户端填写数据到对象中,调用定义的函数就行,服务端继承接口中定义的虚函数,实现数据处理即可。调用也十分简单,从感性上理解,客户端调用数据处理方法,服务端的方法就被调用了,它是一个类似于RPC的机制。
    有了ICE这个强有力的助手,数据发送和接收变得异常容易了,然后我们需要处理的就是连接的维护。
    服务器端不需要维护连接,因为对他来说,服务端就是一个类似回调函数的机制,它并不关心或者不清楚在某一个时刻,自己会被哪个远程主机调用。客户端需要维护连接,因此,类似于模型2中的方法,在客户端独立一个线程,一直尝试连接未连接上的主机即可。
    讲讲这种模型下我的一般设计方法:
     主线程启动后创建两个线程,一个客户端线程,一个服务端线程,服务端线程运行后,就会处于阻塞状态,一直等待消息的到来,客户端在运行后则会一直尝试去发送数据,而主线程下来要做的事情就是:遍历它跟客户端线程共享的那个主机列表,尝试连接每一个没有连接上的主机。
    这就是第三种模型,希望有改进意见的朋友积极发表看法和意见,谢谢!

论坛徽章:
0
发表于 2011-01-06 09:52 |显示全部楼层
第三种模型的一个好处就是,由于ICE使得客户端和服务端的代码变得简单起来,我们可以很轻松的把客户端的功能和服务端的功能用一个程序中的两个线程来实现。这相对于1和2的模型来说,方便多了。

论坛徽章:
0
发表于 2011-01-06 16:33 |显示全部楼层
而对于服务器端程序来说,因为它遍历连接列表进行数据接收,采用的是非阻塞方式,即使客户端的连接已经断开,他调用recv操作,返回的结果跟没有收到数据是一样的,都是0(这个结论我应该没有记错吧,如果有错,望指出)


如果是非阻塞,正常情况下如果没有数据,recv函数会返回-1,并且将错误代码置为EAGAIN,如果recv返回0,其实代表的是远端socket被关闭了

我也对服务器程序设计感兴趣,大家多交流。

论坛徽章:
0
发表于 2011-01-06 16:55 |显示全部楼层
如果是非阻塞,正常情况下如果没有数据,recv函数会返回-1,并且将错误代码置为EAGAIN,如果recv返回0, ...
myxxn 发表于 2011-01-06 16:33



    嗯,谢谢纠正,我晚上查下代码,看看这块具体处理流程!

论坛徽章:
0
发表于 2011-01-07 10:55 |显示全部楼层
这个话题开的太好了,我对这个话题也非常感兴趣。
一般我常用的就是第二种方式,专门开一个监听线程来处理连接,对已经连接好的分到空闲的工作线程中处理,在实际的过程中,我也遇到了客户端不正常断开,造成资源浪费的情况,我采取的方式是再开一个监控线程,来扫描判断每个连接的状态。

论坛徽章:
0
发表于 2011-01-07 11:01 |显示全部楼层
如果是非阻塞,正常情况下如果没有数据,recv函数会返回-1,并且将错误代码置为EAGAIN,如果recv返回0, ...
myxxn 发表于 2011-01-06 16:33



    呵呵,对您的说法我再次做了验证。
对于阻塞和非阻塞的socket,如果server端一直保持recv的操作,对于发送端的异常退出,close并且正常退出,或者没有数据,server端通过recv是不能检测到的,当返回值<0时,errno都是EAGIN,因此能不能这么说,纯粹的recv工作的socket是不能检测对端的退出的?
如果这样的话,还是需要在没有收到数据一段时间后通过发送心跳包来检测连接的状态的。:wink:
不知道我的说法有无纰漏?或者您再做做实验,指出我可能存在的问题,谢谢!

论坛徽章:
0
发表于 2011-01-07 14:34 |显示全部楼层
本帖最后由 duanjigang 于 2011-01-07 14:35 编辑

把myxnn给我的消息贴下,相信他应该不会介意吧,也是为了跟大家分享,呵呵:
你好,那个recv的问题我又做了一个实验,
在阻塞模式下,client自动关闭时,server端的recv收到的却是是0
非阻塞模式下我没来得及重新做,但是我之前是用epoll做的,当client关闭连接时  我会收到一个可读事件,这个时候再去读的话,也是收到的0
您的邮箱可以告诉我一下吗? 我把我的测试代码发你看看有没有问题
我的测试环境:
操做系统:Ubuntu 8.04.3 (Linux 2.6.24-24-generic x86_64 )
g++:g++ (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)

论坛徽章:
0
发表于 2011-01-07 14:38 |显示全部楼层
呵呵,应该跟操作系统关系不大吧。recv本身的操作就是从本地缓冲区中读取数据,应该跟发送端关系不大。
因此,对端状态的探测还是需要心跳包的。

论坛徽章:
0
发表于 2011-01-07 15:33 |显示全部楼层
本帖最后由 myxxn 于 2011-01-07 15:38 编辑

回复 29# duanjigang

恩,心跳协议肯定是必不可少的
不过我想心跳协议重点不在于检查连接是否端掉,连接是否中断从系统里面是肯定可以探测到的,
关键心跳协议能检测到“被远程调用端”是否“死”掉,比如说请求一个远端的服务,连接虽然没断,
但是服务器已经死循环了,这个时候通过心跳协议的超时机制来检测,这时就应该主动把连接断掉,然后重新请求一个可用的服务
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京皓辰网域网络信息技术有限公司. 版权所有 京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP