本帖最后由 delphi2012 于 2012-04-10 10:19:18 编辑

解决方案 »

  1.   

    临晨用了网络调试助手测试了的。问题是同样的,就是在新连接已经上来的情况下,关闭老连接,新连接自动断开。从GRPS终端上看,是服务器主动断开的
      

  2.   

    验证Delphi端的办法:  运行服务器,然后用网络调试助手连接到delphi做的服务器,然后直接结束网络调试助手进程,再用网路调试助手连接服务器,这样服务器上应该有两个连接,一个有效一个异常,服务器尝试关闭异常的那个,看正常的那个网络调试助手是否还在线或者也被强制断开了。移动GPRS应该不会有这种低级错误。
      

  3.   

    谢谢回复。用软件还不能模仿,用网络助手模拟客户端,不管是在本地局域网还是跨越互联网,只要客户端一用任务管理器杀死,
    服务器就立马执行ondisconnect函数。看来得忽然断网了。但是那样连第二个程序也无法开启了。
      

  4.   

    我们公司的GPRS连接是用户UDP做的。用的是C++, 这个可能是DELPHI方面的问题。或者是通讯协议有什么地方不正确。可以考虑用户UDP做一下试试,我过这个GPRS通讯包是我的一个同事做的,我也不太懂。而且C++也不是我的强项。只能提供参考意见!嘿嘿!
      

  5.   

    目前去掉了程序,用网络助手,换成联通的手机卡,用串口助手直接操作SIM300,不启用终端的AVR程序,结果是一样的。就是没有换CMnet出口
      

  6.   

    没大看明白楼主的描述,你的意思是客户端断开后,服务器依然还存在原来的那个SOCKET连接是吗?这个需要用服务器来轮询,根据时钟节拍来清理断开的连接的
      

  7.   


    对,就是这个意思,问题就是清理断开链接的时候,新的连接也被断开了。
    比如,老链接是用的11.22.33.44连接的。
    后来断开了,设备重新上电后重新连接,这个新建立的连接IP地址可能就变化了,可能是11.22.33.55了。那么在服务器上,关闭SOCKET的时候,关闭原来的老的11.22.33.44对应的链接,这个时候,新建立的11.22.33.55的链接就断开了。实在是太搞笑了,
      

  8.   

    我不太懂得GPRS网络的运行原理,我初步推测,可能是移动的网络自动记录每个SIM卡的上网情况,当该设备断开的时候,移动服务器缓存了该设备对应的IP数据。当该设备重新上电,上了GSM网络的时候,服务器又把上一次的IP地址对应的缓存信息送到新IP地址上去了,而上一次的IP地址对应的是TCP的关闭信息,所以,新IP地址也就接受了这样的请求,就自动关闭了。
      

  9.   

    问题出现了!!无论调用的close 函数或者CloseDelayed。关闭的明明是已经半死掉的以前的socket会话,但是新的已经建立起来的会话,却会被关闭程序了。断线了。遇过类似情况  与GPRS无关 与 TWSocketServer具体实现有关 
    是你的程序问题  TWSocketServer也有责任
    好像 旧连接断线后  它的SocketHandl 就会失效  新连接 连上后会分配SocketHandl 值为旧连接的 因为已断开  
    这时 再断开旧连接 就变成断开了新连接  旧连接实际已断开 但 SocketServer状态不正确 
      

  10.   

    服务端你是怎么关闭客户端的??
    按ip?
    还是俺ip+(peer)port?
    还是俺连接主机名(包括你自己定义的名称)?搞清楚了,你再查看是不是对这些都发送了断开信号。。
      

  11.   

    ------兄台,你说的貌似在理啊,我得研究一下。看来得本地抓包确认一下。我是用的表示socket客户端的client对象提供的方法进行断开的,也就是说,我是按照指针进行操作的,操作的依据就是对方最后一次发包时间跟当前对比,确认是否在线的。
      

  12.   


     我是在socket server的事件函数中,引用事件函数中代表客户端的参数,就是代表客户端的一个对象,然后使用这个对象提供的close函数。按照上一个兄台的意思,是指针未变,而指针对应的对象已经悄悄发生变化了,所以就是老指针操作了新对象了。
      

  13.   

    ICS我没用过.我的工具用的是lazarus, + indy 10.
    我发现在onconnect,或ondisconnect事件就对客户端线程进行很多操作的话,服务端和客户端都很难断开,出现一些其他问题,发现有些连接线程会绕过onconnect事件.所以我把那些操作尽量放到onExecute事件中.
    譬如这样
    procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
    begin
      AContext.Data:=TUserClass.create;
      {接入点跟断开点越简单越好,否则难以断开
      一句话,所有的动作在execute里头由同步链进行}
      //with TUserClass(AContext.Data) do
      //    begin
      //    FContext:=AContext;
      //    Fip:=AContext.Connection.Socket.Binding.PeerIP;
      //    FPeerPort:=AContext.Connection.Socket.Binding.PeerPort;
      //    FUserName:='';
      //    end;
    end;  希望这一看法能对你有帮助.
      

  14.   

    CSDN里面有高人啊,CSDN里面有好人啊。高人,不是单一的技术层面的,还包括阅历,包括对软件产品的理解,见地。谢谢大家,我正在大规模改动代码。。如真是如此,马上结贴送分啊。
      

  15.   

    其实 TWSocketServer 是自带客户端断开检测的,正常客户端断开,会向服务器发送一个断开消息,服务器收到后出发 sessionclose,这里可以处理。
    可是有些客户端异常断开,服务器收不到断开消息,这样服务器就会一直保留这个socket,俗称死链接,其实可以用keepalive方法来定期检测客户端是否存活,这样TWSocketServer 会自动关闭死链接。
      

  16.   

    移动的GPRS 我们一直在用的,好像没有你说的问题,我觉得还是服务端问题吧。
    你试试让你的GPRS连接IIS看看他会不会这样。
      

  17.   

    回覆:
    很长时间才来。我抓包分析了。上位机close socket之后,自动发送FIN置位的IP包 ,IP是正常的,IP地址和端口都是对的上的,程序本身没有错误,这么简单的程序,要是有问题,那谁还敢用控件呢?自动发终结包,这是操作系统的自动行为,正常情况下就是该这么做,相同的IP甚至发送四五次。可见不见对方回应,因为抓不到对方的回包。  好,我投降,我不close socket还不行吗?但是这样的话,状态为ESTABLISHED的会话,成倍增加,从不断开,资源不得到释放,我的上位机程序还得一个个的遍历。也满 我的问题就是,象GPRS这种没有操作系统的、单线程的、靠SIM300等外置芯片实现TCP/IP协议的设备,到底该如何处理回话呢?难道让上位机定时重启吗?
      

  18.   

    我以前有过类似的,发现每隔一段时间断开,后来查出是的确是sim卡的问题,那个IP的是动态分配的每一段时间变一下,后来换了固定IP的就不会断了。
      

  19.   


    我们也遇到过类似的问题。 解决办法:
    1)客户端每隔一段时间发心跳包上来,如果超过时间没有收到心跳信号,就删掉socket
    2) 客户端每次连接的时候,主动发送一个设备id上来,你在设备编码时候保证id不重复。
       如果断了重连时候,服务器端检测有重复的id,就把前面的id所对应socket删除。然后接受新的连接。
        用一个数组管理在线的设备id即可。
    我们的应用是一个  gprs的中间件,可以支持上千 socket连接,用c写的,比用控件效率高一些。如果你的服务器端懒得写,可以调用我们的中间件,我们来帮你维持socket, 把收到的数据写入你的指定的数据库,或者开一个接口你来读。我们开发这个的目的就是降低大家写gprs服务器端的工作量。以在线saas方式运行。测试地址:
    http://184.169.160.55/GPRS_Free_Test/这个接口是针对gprs打印机的,可以根据你的需要写针对你的接口
      

  20.   

    其实定时GRPS断线的问题,我倒不担心。现在的测试,十几个小时都可以在线。关键楼上说的,删除SOCKET,结果就问题了。把正常的也给断开了。好像移动的网管系统太智能了,
    可以做到父债子还的地步。关闭老连接的时候,自动关闭新的连接。因为移动认为----你还是你,今天的你,就是昨天的你
      

  21.   

    我们讨论的是非正常的情况下的断开啊。 如果你的同一台设备再次连接上来,说明前面的已经断了,你只是在服务器数据结构上删除这个socket句柄,应该和移动网络没关系了,除非你又向客户端发出什么“我想断开”的信号,否则运营商不可能知道。你如果是用的线程,就直接关线程。进程,就直接关进程。
      

  22.   

     
    补充:我说的是c写程序自己控制socket握手情况下的判断,你用的这个控件我没用过,抱歉, 也许不适合你的情况
      

  23.   

    冒似楼主搞错了,调用控件的close应该是关闭整个TCP服务,所以所有的连接都会被断开.你要关某个特定的连接应该用别的方法
      

  24.   

    回避了SOCKET的问题。GPRS单独是一个对象,他根据SOCKET的最后活动时间来判定GPRS是否在线