- 论坛徽章:
- 0
|
本帖最后由 yearn4fd 于 2014-08-18 12:50 编辑
学perl有一段时间了,最近用perl做一个应用,遇难题求解答,谢谢。
情况大致是这样:远程有一业务服务器(移动网络的交换机),
我们可以 raw socket 接入。发起移动业务指令(MML人机对话指令)之前需要进行鉴权,
鉴权时间开销不少,有1秒多一点,业务指令执行挺快。应用主要是采集远程交换机上的数据(查询)。
原来采用短连接模式,每次都要鉴权,效率低下。我想将之改为长联接方式,但改造过程遇到一些难题。
新的应用先建立一个与远程服务器连接的socket 句柄,然后又在本机上创建自已的socket服务器,对外提供最多10路同时接入。
说穿了,它就是一个socket代理服务器。如下图。
移动交换机远程socket接入服务器 <--------------长连接————————[代理socket服器 listen accept fork]〈〈〈〈〈〈〈〈〈〈
注:fork出来的子进程可接入多路源端。
接入交换机我写成独立的package,主要处理连接及鉴权,package对外提供子例程。
在主程序中use package_mobile 之后再调用 package_mobile::f_mobile($SOCK,$error)便可得到已完成鉴权的socket 句柄。
代理socket服务器是阻塞方式实现(对方要求最好是阻塞式)。
在代理socket服务器中,fork 之后需要对package_mobile::f_mobile($SOCK,$error)生成的$SOCK进行操作,操作时都使用flock锁定。
且在子进程中操作$SOCK时使用了eval保护。程序写好后一次运行成功,比之以前效率高多了。但过不了多久,问题来了。
1、对方服务器在我发起的长连接空闲一段时间后(没有需求接入),会自动中断我的创建的$SOCK,我想检测中断前的通知,但没有检测到。
也就是说,空闲一段后接入到代理服务器发起对$SOCK的操作均失败。我试过$SOCK->sockopt(SO_KEEPALIVE,1); 但没起作用
(可能对方不支持吧)。我想到周期性发起心跳指令,但除非再加一层fork,否则在阻塞式的代理服务器代码里,我真想不出如何找个地方
周期性发起心跳。大家帮忙想下,怎么加。再加层fork的话,相当于父进程周期性发心跳,子进程监听,孙进程服务于10路接入。
2、在不改为两次调用fork的前提下,我想到信号,在主程序内设了$SIG{USR1},并在子进程中操作$SOCK时设置了 超时处理:
local $SIG{ALRM} = sub { print "Timeout\n";die "MYTimeout\n";};
在设定时间内出错或未完成时,子进程向父进程发送USR1信号,USR1信号处理函数中重新调作 package_mobile::f_mobile($SOCK,$error),
我的想法无非是重新创建连接远程服务器的socket句柄,但很奇怪,客户端新发起对$SOCK的操作还是失败的。
难道是我的想法根本就不可能实现?
|
|