我在python中做一些基本的套接字编程。但是我很难弄清楚我的回忆者如何注意到回声已关闭它的连接,没有持续的ping / pong或超时。
echoclient.py
#echoclient
import sys
import socket
import os
import datetime
def log(s):
return datetime.datetime.now().strftime('%H:%M:%S') + ' - ' + s
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9000))
while 1:
try:
foo = raw_input('what do you want to send?: ')
if len(foo) > 0:
s.send(foo)
except KeyboardInterrupt:
print 'shutting down connection'
s.close()
break
data = s.recv(1024)
if data:
print log('Recieved'), repr(data)
echoserver.py
#echoserver
import sys
import socket
import os
import datetime
def log(s):
return datetime.datetime.now().strftime('%H:%M:%S') + ' - ' + s
port = 9000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', port))
s.listen(5)
while 1:
conn, addr = s.accept()
conn.settimeout(10)
print 'Connected by', addr
while 1:
try:
data = conn.recv(1024)
if data:
print log(repr(data))
conn.send(data)
except KeyboardInterrupt:
print 'Closing connection ', addr
conn.close()
sys.exit(1)
except:
print 'Exception caught! closing connection ', addr
conn.close()
break
现在服务器知道客户端已经死亡的唯一方法是conn.settimeout(10)
当客户端断开连接时,如果它们之间没有constat ping / pong消息或settimeout,我怎样才能获得服务器的异常。
我的下一步是在echoclient和echoserver之间创建一个echoproxy,我需要使用线程/多处理来实现这一目标吗?任何提示或指示?
欢迎任何其他有关不良/良好做法的评论
谢谢!
答案 0 :(得分:1)
据我所知,套接字库在clients disconnect时已收到消息。
严格地说,在关闭套接字之前,你应该在套接字上使用shutdown。关闭是对另一端套接字的建议。根据您传递的论点,它可能意味着“我不会再发送了,但我仍然会听”,或者“我不是在听,也不是很好!”。然而,大多数套接字库都习惯于程序员忽略使用这种礼仪,通常关闭与shutdown()相同;关()。因此在大多数情况下,不需要显式关闭。
服务器可以通过接收0字节来检测“EOF”。它可以假设它有完整的请求。服务器发送回复。如果发送成功完成,那么客户端仍在接收。
当另一端突然断开连接(如网络故障或崩溃)时超时发挥作用。
在上面的服务器代码中,您应该能够使用以下方法立即检测客户端断开连接:
if data:
# process data
else:
# client disconnected
答案 1 :(得分:0)
Python套接字库是一个低级实现,因此使用起来可能很棘手。我建议使用更高级别的东西,比如Twisted。您可以使用connectLost方法在Twisted中完成您正在寻找的内容。
from twisted.internet.protocol import Protocol
class Echo(Protocol):
def connectLost(self, reason):
pass
有关详细信息,请参阅http://twistedmatrix.com/documents/current/core/howto/servers.html。
(扭曲也可能使代理更容易实现。)
答案 2 :(得分:0)
在致电socket.shutdown()
之前使用socket.close()
。阅读socket.close()
here