1+ import errno
2+ import queue
3+ import select
4+ import socket
5+ import sys
6+
7+ class ServerSocket :
8+
9+ def __init__ (self , mode , port , onReceiveMsg , onCreateConn , onCloseConn , max_connections = 1000 , recv_bytes = 2048 ):
10+ # Handle the socket's mode.
11+ # The socket's mode determines the IP address it binds to.
12+ # mode can be one of two special values:
13+ # localhost -> (127.0.0.1)
14+ # public -> (0.0.0.0)
15+ # otherwise, mode is interpreted as an IP address.
16+ if mode == "localhost" :
17+ self .ip = mode
18+ elif mode == "public" :
19+ self .ip = socket .gethostname ()
20+ else :
21+ self .ip = mode
22+
23+ self .controlSocket = None
24+ self .clientSocket = []
25+
26+ # Handle the socket's port.
27+ # This should be a high (four-digit) for development.
28+ self .port = port
29+ if type (self .port ) != int :
30+ print ("port must be an int" , file = sys .stderr )
31+ raise ValueError
32+
33+ # Save the callback
34+ self .onReceiveMsg = onReceiveMsg
35+ self .onCreateConn = onCreateConn
36+ self .onCloseConn = onCloseConn
37+
38+ # Save the number of maximum connections.
39+ self ._max_connections = max_connections
40+ if type (self ._max_connections ) != int :
41+ print ("max_connections must be an int" , file = sys .stderr )
42+ raise ValueError
43+ # Save the number of bytes to be received each time we read from
44+ # a socket
45+ self .recv_bytes = recv_bytes
46+
47+ def run (self ):
48+ # Start listening
49+ # Actually create an INET, STREAMing socket.socket.
50+ self ._socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
51+ # Make it non-blocking.
52+ self ._socket .setblocking (0 )
53+ # Bind the socket, so it can listen.
54+ self ._socket .bind ((self .ip , self .port ))
55+
56+ self ._socket .listen (self ._max_connections )
57+ # Create a list of readers (sockets that will be read from) and a list
58+ readers = [self ._socket ]
59+ # Create a similar dictionary that stores IP addresses.
60+ # This dictionary maps sockets to IP addresses
61+ IPs = dict ()
62+ self ._stop = False
63+
64+ # Now, the main loop.
65+ print ("TCP 服务器已启动" )
66+ while readers and not self ._stop :
67+ #print("Block until a socket is ready for processing.")
68+ read , _ , err = select .select (readers , [], readers )
69+ # Deal with sockets that need to be read from.
70+ for sock in read :
71+ if sock is self ._socket :
72+ # We have a viable connection!
73+ try :
74+ client_socket , client_ip = self ._socket .accept ()
75+ except Exception :
76+ break
77+
78+ # Make it a non-blocking connection.
79+ client_socket .setblocking (0 )
80+ # Add it to our readers.
81+ readers .append (client_socket )
82+ # Make a queue for it.
83+ # queues[client_socket] = queue.Queue()
84+ IPs [client_socket ] = client_ip
85+ self .onCreateConn (self , client_socket , client_ip )
86+ print (f"readers length { len (readers )} " )
87+ else :
88+ # Someone sent us something! Let's receive it.
89+ try :
90+ data = sock .recv (self .recv_bytes )
91+ except socket .error as e :
92+ if e .errno == errno .ECONNRESET :
93+ # Consider 'Connection reset by peer'
94+ # the same as reading zero bytes
95+ data = None
96+ else :
97+ raise e
98+ if data :
99+ self .onReceiveMsg (self , sock , IPs [sock ], data )
100+ else :
101+ #print("We received zero bytes, so we should close the stream")
102+ # Stop writing to it.
103+ # Stop reading from it.
104+ readers .remove (sock )
105+ sock .close ()
106+ self .onCloseConn (self , sock , IPs [sock ])
107+
108+ # Deal with erroring sockets.
109+ for sock in err :
110+ #print("Remove the socket from every list.")
111+ readers .remove (sock )
112+ # Close the connection.
113+ sock .close ()
114+
115+ def stop (self ):
116+ self ._stop = True
117+ self ._socket .close ()
0 commit comments