Prior to the PHP version of the WebSocket package, see websocket--php Combat, the recent use of Python to do some functions, need to use the websocket operation, so, referring to the previous implementation, the implementation of this Python version. SOURCE See Https://github.com/OshynSong/wspy.
Overall implementation, it is necessary to set up a socket listening port, which needs to use the Socket standard library module, and then need to operate on the network byte stream, this aspect python has a struct standard library module, this is very useful, and also involves the encryption and decryption operations, There are also hashlib modules and SHA modules for use. In particular, to summarize here, the purpose is mainly
1 Memo
2. Summary and thinking
1 socket Operation 1 Local socket established
General process for establishing a TCP server:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.bind((addr,port))sock.listen(10)
Set up a local socket, and bind the address and port to listen.
2 Concurrent Connection Policies
After the
, you need to use different policies to handle multiple client connections, the most common way is to use accept blocking directly, so that the server can only process one client connection at a time. The Python standard library then provides a select module with a processing strategy for the different concurrent connections of Select, poll, and Epoll. Poll and Epoll can only be used under Linux, and Epoll can be used in versions after Linux 2.6. Of course, the concurrent processing effect, Epoll than poll performance better, poll than select Performance more excellent. But select can be used on a variety of platforms, in order to be compatible with the Windows system, this implementation is using the Select Policy, as follows:
... #接上述socket建立代码 while true : RS, ws, ES = Select.select ([sock], [], []) for R in rs: if R i S sock: #r is the server-side socket clisock,addr = r.accept () r.connect ( Clisock) #建立于客户端连接 else : try : Data = R.RECV (Bufferlen) ... #处理客户端连接发送的数据 ...
The poll method is also a method within the Select module, which is simpler to use than a select. First use poll to create a poll object, and then use its Register method to register a file descriptor, unregister method can remove the registered object. You can then call the poll method to get a list of (fd,event) formats, FD is the file descriptor, and the event represents the events that occurred. Event is a bitmask that can be bitwise operated using the constants of the Select module.
Polling event constants in the Select module:
Event name |
Description |
Pollin |
Reading data from a file descriptor |
Pollpri |
Read emergency data from a file descriptor |
Pollout |
The data for the file descriptor is ready to be written without blocking |
Pollerr |
Error condition related to file descriptor |
Pollhup |
Pending, Connection lost |
Pollnval |
Invalid request, connection not open |
The following is a sample code that uses the poll policy:
... #接上述socket建立代码Fdmap = {Sock.fileno (): S}p = Select.poll () p.register (sock) while True: Events = P.poll () forFd,eventinchEventsifFdinchFdmap:#本地socketC,ADDR = Sock.accept ()Print ' Connected from ', addr P.register (c) Fdmap[c.fileno ()] = CelifEvent & Select. Pollin:data = fdmap[fd].recv (buffer) ...#数据操作 elifEvent & Select. Pollerr:#断开连接P.unregister (FD)delFDMAP[FD] ...
2 struct processing byte data
This standard library module is used to convert Python data values to C-style data types, especially binary files and network byte data. The Main method:
Struct.pack (FMT, V1, v2 ...)
Struct.pack_into (FMT, buffer, offset, v1, v2 ...) (the position of v1,v2 equivalent in the FMT format after the buffer string begins with offset)
Struct.unpack (FMT, String)
Struct.unpack_from (fmt, buffer [, offset=0])
Struct.calcsize (FMT) (calculates the length of the FMT)
The above is mainly the method of directly using the struct module, each FMT needs to be done separately, if reuse, you can use the struct provided by the struct class, after using the FMT instantiation of the struct object, call a similar method can be reused, and so the performance of using object invocation is better is more efficient than directly using the above method calls.
Pack (V1,v2 ...)
Pack_into (buffer, offset, v1, v2 ...)
Unpack (String)
Unpack_from (buffer, offset=0)
Format: Returns the FMT string used by the instantiated struct object
Size: Returns the length of the FMT string
The use of one of the most critical format strings.
The first is the byte order:
Character |
Byte Order |
Size |
Alignment |
@ |
Native |
Native |
Native |
= |
Native |
Standard |
None |
< |
Little-endian |
Standard |
None |
> |
Big-endian |
Standard |
None |
! |
Network (= Big-endian) |
Standard |
None |
Then the format uses special characters, as shown in the following table:
Format |
C Type |
Python Type | Standard
size |
X |
Pad byte |
No value |
|
C |
Char |
string of length 1 |
1 |
B |
Signed Char |
Integer |
1 |
B |
unsigned char |
Integer |
1 |
? |
_bool |
bool |
1 |
H |
Short |
Integer |
2 |
H |
unsigned short |
Integer |
2 |
I |
Int |
Integer |
4 |
I |
unsigned int |
Integer |
4 |
L |
Long |
Integer |
4 |
L |
unsigned long |
Integer |
4 |
Q |
Long Long |
Integer |
8 |
Q |
unsigned long long |
Integer |
8 |
F |
Float |
Float |
4 |
D |
Double |
Float |
8 |
S |
Char[] |
String |
|
P |
Char[] |
String |
|
P |
void * |
Integer |
|
3 Encryption and decryption processing
The Hashlib standard library module provides all the commonly used cryptographic decryption hashing methods, which are used to:
Hashlib.update (ARG): The hash object is updated with the ARG string, and multiple calls are equivalent to connecting all ARG strings together
Hashlib.digest (): Returns the hash value of the string passed to the Update method
Hashlib.hexdigest (): Returns the hexadecimal string representation of the hash value
Hashlib.copy (): Returns a copy of a hash value
WebSocket in the handshake phase need to obtain the key to the client, and then use SHA1 and base64 to encrypt processing after sending to the client for handshake.
‘258EAFA5-E914-47DA-95CA-C5AB0DC85B11‘).digest() acceptKey = base64.b64encode(sha1Encrypt)
In general, using Python to achieve these operations is very convenient, compared with PHP more concise, highlighting the simplicity of the Python language essence!
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
WebSocket Summary of Python implementations--wspy