Python Socket programming details
- 2020-05-27 06:15:35
- OfStack
When programming socket with Python, you need to use the blocking (default) method to read the data stream, so you need to deal with the end of the data every time, which is too troublesome. And the Internet also did not find a good package, so I wrote a simple package.
Packaging ideas
1. Each request from the client sends an SocketRequest object, which encapsulates the specific data. json is used here. For the data to be sent, an end symbol is automatically added (EOF = '0x00').
2. When the server receives the data, it generates the complete data according to the identifier of the terminator and unpacks it into SocketRequest objects.
3. The server generates SocketResponse objects according to the content of SocketRequest. Here, an SimpleRequestHandler class is used for processing.
4. The server sends SocketResponse to the client. There is also a need to do a package encapsulation, will automatically add a terminal identifier (EOF = '0x00').
5. When the customer receives the data, it generates the complete data according to the identifier of the terminator, unpackages it into SocketResponse objects, and returns.
Wrapper class
sockets.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import pickle
import thread
PORT = 12345
EOF = '0x00'
class SocketServer(object):
def __init__(self, port=None):
self.port = port
def startup(self):
sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock_server.bind(('0.0.0.0', self.port))
sock_server.listen(0)
while True:
sock, address = sock_server.accept()
thread.start_new_thread(self.__invoke, (sock, address))
def shutdown(self):
pass
def __invoke(self, sock, address):
try:
full_data = ''
while True:
data = sock.recv(1024)
if data is None:
return
full_data += data
if full_data.endswith(EOF):
full_data = full_data[0:len(full_data) - len(EOF)]
request = pickle.loads(full_data)
response = SimpleRequestHandler().handle(request)
sock.sendall(pickle.dumps(response) + EOF)
return
except Exception as e:
print e
finally:
sock.close()
class SocketClient(object):
def __init__(self, host, port):
self.host = host
self.port = port
def execute(self, request):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.host, self.port))
try:
sock.sendall(pickle.dumps(request) + EOF)
full_data = ''
while True:
data = sock.recv(1024)
if data:
full_data += data
if full_data.endswith(EOF):
full_data = full_data[0:len(full_data) - len(EOF)]
response = pickle.loads(full_data)
return response
else:
return None
except Exception as e:
print e
return None
finally:
sock.close()
class SocketRequest(object):
def __init__(self, data):
self.data = data
def __repr__(self):
return repr(self.__dict__)
class SocketResponse(object):
def __init__(self, data):
self.data = data
def __repr__(self):
return repr(self.__dict__)
class SimpleRequestHandler(object):
def __init__(self):
pass
def __repr__(self):
return repr(self.__dict__)
def handle(self, request):
return SocketResponse(request.data)
test
socket_server.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from agent.sockets import *
ss = SocketServer(PORT)
ss.startup()
socket_client.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pickle
from agent.sockets import *
sc = SocketClient('localhost', PORT)
request = SocketRequest('abc')
response = sc.execute(request)
print request
print response
Run the test
First, run socket_server.py
Then, run socket_client.py