使用delphi7+原生socket函数写了一个TCPIP通讯服务器,实现了一个通过 原生select()来检测当前连接是否有效的功能,
在内部测试时,没有问题,能有效检测各种设备的断线与重练,效果较好。但部署到应用时,出现了问题,select老返回超时.但使用recv的接收与发送则正常!现在请高手指点一二,看看问题在哪里。
代码:
  LTime.tv_sec := ATimeout div 1000;
  LTime.tv_usec := (ATimeout mod 1000) * 1000;
  Result := Select(0, AReadSet, AWriteSet, AExceptSet, @LTime);
其中:LTime\AReadSet\AWriteSet 每次检查都重新设置了。
通讯模式:阻塞通讯。
内部网络环境说明:
内部公示网络、使用192.168的网段,设备6-10台,select可读检测正常(判断当前连接是否有效)、设备数据的发送与接收也正常。外部网络环境:
服务器端:程序部署在服务器上,使用192.168的内网IP与端口, 有固定外网IP端口 转发数据到 服务器上。
设备部署:通过ADSL网络自动拨号后,设备跨外网发送数据到   外网IP与端口。现象:数据通讯发送与接收正常,但 select可读检查每次都返回0,设备数量超过20台。设备通讯:单台设备通讯间隔不超过3秒,有应用心跳包存在。疑问:
为何select可读检测在外网实际应用时,总返回为0,但此时使用recv的接收与send发送又是正常的?
此问题困恼多日,无法找到原因,还请高手指点一二,谢谢!

解决方案 »

  1.   

    Select的时间单位好像是百万分之一秒?
    会不会因此在延时大一点的公网就被卡了?
      

  2.   

    阻塞式,超时了呗,用非阻塞是,线程处理网上有socket的6中模式,可以看看
      

  3.   

    自己还是不明白原因所在。
    不明白为何建立好通讯后,都在正常发送数据,但这个SELECT检测有问题。
    且内网正常、外网不正常。。
      

  4.   

    arg:=1;
        ioctlsocket(FSocket, integer(FIONBIO), arg);  //设置为非阻塞模式connect(FSocket, @psa, sizeof(psa)));
    timev.tv_sec := 5;  //超时5秒
        timev.tv_usec := 0;
        arg := select(0, @fd_read, @fd_read, nil, @timev);
        if (arg = 0) or (arg= SOCKET_ERROR) then  Exit ;  //连接失败
        arg:=0;
        ioctlsocket(FSocket, integer(FIONBIO), arg);  //设置为阻塞模式