我从https://docs.python.org/3.5/library/socketserver.html在Python 3.5中实现了Server-Client示例。该示例适用于循环中的第一条消息,但服务器始终发送FIN-Flag,我不明白为什么。
服务器:
import socketserver
class MyTCPHandler(socketserver.BaseRequestHandler):
"""
The request handler class for our server.
It is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""
def handle(self):
# self.request is the TCP socket connected to the client
self.data = self.request.recv(1024).strip()
print("{} wrote:".format(self.client_address[0]))
print(self.data)
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
# Create the server, binding to localhost on port 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
# Activate the server; this will keep running until you
# interrupt the program with Ctrl-C
server.serve_forever()
客户端:
import socket
import sys
import time
HOST, PORT = "localhost", 9999
data = " ".join(sys.argv[1:])
# Create a socket (SOCK_STREAM means a TCP socket)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
while True:
print("Try")
sock.sendall(bytes(data + "\n", "utf-8"))
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
print("Sent: {}".format(data))
print("Received: {}".format(received))
time.sleep(5)
Wireshark的:
17771 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 52 59886 → distinct(9999) [SYN] Seq=0 Win=8192 Len=0 MSS=65495 WS=256 SACK_PERM=1
17772 12:20:03.585705 127.0.0.1 127.0.0.1 9999 59886 TCP 52 distinct(9999) → 59886 [SYN, ACK] Seq=0 Ack=1 Win=8192 Len=0 MSS=65495 WS=256 SACK_PERM=1
17773 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 40 59886 → distinct(9999) [ACK] Seq=1 Ack=1 Win=8192 Len=0
17774 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 49 59886 → distinct(9999) [PSH, ACK] Seq=1 Ack=1 Win=8192 Len=9
17775 12:20:03.585705 127.0.0.1 127.0.0.1 9999 59886 TCP 40 distinct(9999) → 59886 [ACK] Seq=1 Ack=10 Win=7936 Len=0
17776 12:20:03.585705 127.0.0.1 127.0.0.1 9999 59886 TCP 48 distinct(9999) → 59886 [PSH, ACK] Seq=1 Ack=10 Win=7936 Len=8
17777 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 40 59886 → distinct(9999) [ACK] Seq=10 Ack=9 Win=7936 Len=0
17778 12:20:03.585705 127.0.0.1 127.0.0.1 9999 59886 TCP 48 distinct(9999) → 59886 [PSH, ACK] Seq=9 Ack=10 Win=7936 Len=8
17779 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 40 59886 → distinct(9999) [ACK] Seq=10 Ack=17 Win=7936 Len=0
17780 12:20:03.585705 127.0.0.1 127.0.0.1 9999 59886 TCP 40 distinct(9999) → 59886 [FIN, ACK] Seq=17 Ack=10 Win=7936 Len=0
17781 12:20:03.585705 127.0.0.1 127.0.0.1 59886 9999 TCP 40 59886 → distinct(9999) [ACK] Seq=10 Ack=18 Win=7936 Len=0
17795 12:20:08.588160 127.0.0.1 127.0.0.1 59886 9999 TCP 40 59886 → distinct(9999) [FIN, ACK] Seq=10 Ack=18 Win=7936 Len=0
17796 12:20:08.588160 127.0.0.1 127.0.0.1 9999 59886 TCP 40 distinct(9999) → 59886 [ACK] Seq=18 Ack=11 Win=7936 Len=0
答案 0 :(得分:0)
这一切都在 socketserver.py ([Python]: socketserver — A framework for network servers)和其他一些地方:我将使用版本 3.5.4 作为参考( doc引用将是版本 3 特定的):
BaseServer.serve_forever(self, poll_interval=0.5)
(#215 )调用_handle_request_noblock
(#234 ):
self._handle_request_noblock()
BaseServer._handle_request_noblock(self)
(#306 )调用process_request
(#313 ):
self.process_request(request, client_address)
BaseServer.process_request(self, request, client_address)
(#335 )调用shutdown_request
(#342 ):
self.shutdown_request(request)
TCPServer
延伸BaseServer
(#370 ):
class TCPServer(BaseServer):
TCPServer
覆盖shutdown_request
(#489 ):
def shutdown_request(self, request):
"""Called to shutdown and close an individual request."""
try:
#explicitly shutdown. socket.close() merely releases
#the socket and waits for GC to perform the actual close.
request.shutdown(socket.SHUT_WR)
except OSError:
pass #some platforms may raise ENOTCONN here
self.close_request(request)
request.shutdown(socket.SHUT_WR)
request
是socket.socket
([Python]: Socket Objects)实例 socket.socket.shutdown
在 $ {PYTHON_SRC_DIR} /Modules/socketmodule.c (#3986 )中定义:
static PyObject *
sock_shutdown(PySocketSockObject *s, PyObject *arg)
{
int how;
int res;
how = _PyLong_AsInt(arg);
if (how == -1 && PyErr_Occurred())
return NULL;
Py_BEGIN_ALLOW_THREADS
res = shutdown(s->sock_fd, how);
Py_END_ALLOW_THREADS
if (res < 0)
return s->errorhandler();
Py_INCREF(Py_None);
return Py_None;
}
如图所示,它调用原生shutdown
API :
根据上面的 MSDN 链接(未找到官方的 Ux 相关文档,但我不能说我试过很努力的搜索):
如果如何参数是SD_SEND,则不允许后续调用send函数。对于TCP套接字,在接收方发送和确认所有数据后,将发送 FIN 。
注意( Ux &lt; - &gt; Win 转换): SHUT _ * 和 SD_ * 相应的常量具有相同的值(例如 SHUT_WR = SD_SEND = 1)