FreeBSD上的Python中的SO_KEEPALIVE不起作用

时间:2016-11-28 17:01:33

标签: python networking tcp websocket

我使用这个库:

https://github.com/dpallot/simple-websocket-server

当我运行以下程序(在FreeBSD上同时使用Python 2.7和Python 3.5)时,它在305秒后超时,尽管我设置SO_KEEPALIVESO_KEEPALIVE不起作用!

#!/usr/bin/python

import socket
from SimpleWebSocketServer import SimpleWebSocketServer, WebSocket

class MyWebSocket(WebSocket):
    def handleConnected(self):
        print(self.address, 'connected')
        self.client.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        #self.client.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 3600)
        #self.client.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 3600)
        self.client.settimeout(3600)


class MyWebSocketServer(SimpleWebSocketServer):
    def _decorateSocket(self, sock):
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        #sock.setsockopt(socket.SOL_TCP, socket.TCP_KEEPIDLE, 3600)
        #sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 3600)
        sock.settimeout(3600)
        print("socket decorated: ", sock.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE))
        return sock


server = MyWebSocketServer('', 9000, MyWebSocket)
server.serveforever()

我使用以下HTML进行测试:

<html><head><meta charset="UTF-8"/><title>WebSocket</title>
<script type="text/javascript">
var socket;
function setupWebSocket() {
  var host = "ws://XXX:9000/";
  try {
    socket = new WebSocket(host);
    var start = (new Date()).getTime();
    socket.onclose = function(msg) {
      var secs = (new Date()).getTime() - start;
      alert("disconnected after "+(secs/1000)+" sec");
    };
  }
  catch(ex){
    alert(ex);
  }
}
</script>

</head>
<body onload="setupWebSocket()">
</body>
</html>

奇怪的是,类似的代码可以与PHP一起使用。

1 个答案:

答案 0 :(得分:2)

TCP keep alive旨在检测对等方是否不再可访问,并确保中间有状态数据包筛选器(如在SoHo路由器中用于NAT)不会丢弃状态。它的工作原理是发送有效负载大小为0的“空”TCP数据包。

由于TCP保持活动状态不传输任何数据,如果您在应用程序级别有空闲超时(无数据传输时触发),则无效。为此,您需要发送实际数据,即某种心跳。为此,Websockets有“ping”和“pong”,请参阅documentation in python