Python socketserver发送FIN-Flag

时间:2017-10-17 08:39:53

标签: python tcp

我从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

1 个答案:

答案 0 :(得分:0)

这一切都在 socketserver.py [Python]: socketserver — A framework for network servers)和其他一些地方:我将使用版本 3.5.4 作为参考( doc引用将是版本 3 特定的):

  1. BaseServer.serve_forever(self, poll_interval=0.5)#215 )调用_handle_request_noblock#234 ):

    self._handle_request_noblock()
    
  2. BaseServer._handle_request_noblock(self)#306 )调用process_request#313 ):

    self.process_request(request, client_address)
    
  3. BaseServer.process_request(self, request, client_address)#335 )调用shutdown_request#342 ):

    self.shutdown_request(request)
    
  4. TCPServer延伸BaseServer#370 ):

    class TCPServer(BaseServer):
    
  5. 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)
    
  6. request.shutdown(socket.SHUT_WR)

    1. 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;
      }
      
    2. 如图所示,它调用原生shutdown API

      根据上面的 MSDN 链接(未找到官方的 Ux 相关文档,但我不能说我试过很努力的搜索):

        

      如果如何参数是SD_SEND,则不允许后续调用send函数。对于TCP套接字,在接收方发送和确认所有数据后,将发送 FIN

      注意 Ux &lt; - &gt; Win 转换): SHUT _ * SD_ * 相应的常量具有相同的值(例如 SHUT_WR = SD_SEND = 1)