公共server代码
wrapper_socket/server.py
# -.- coding:utf-8 -.-
import socket
HOST = '127.0.0.1'
PORT = 50007
EOL1 = b'\r\n'
EOL2 = b'\r\n\r\n'
sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST, PORT))
sock.listen(1)
while True:
try:
data = b''
connection, address = sock.accept()
while True:
data += connection.recv(4096)
if EOL1 in data or EOL2 in data:
break
connection.sendall(data)
connection.close()
finally:
connection.close()
独立的客户端
wrapper_socket/client.py
# -.- coding:utf-8 -.-
import sys
import socket
python_3 = sys.version_info >= (3,)
IDLE = 'idle'
CONN = 'connect'
SEND = 'send'
class TCPClient:
_clients = {}
def __init__(self, server_address,
family=socket.AF_INET,
_type=socket.SOCK_STREAM):
self.server_address = server_address
self.family = family
self.type = _type
self.sock = None
self.__state = IDLE
self._clients.update({id(self): self})
self.connect()
def __enter__(self):
return self
def __exit__(self, *exc_info):
return self.exit()
def _connect(self):
self.__state = CONN
if not all(self.remote_address()):
self.sock = socket.socket(self.family, self.type)
self.sock.connect(self.server_address)
return self.sock
def connect(self):
# 判断是否与远程服务器建立连接.
if self.sock is None:
self._connect()
else:
self.reconnect()
return self.sock
def reconnect(self):
self.close()
return self._connect()
def send(self, data):
if self.__state == IDLE:
self.connect()
result = self._send(data)
self.close()
return result
def _send(self, data):
self.__state = SEND
# python 3 环境下, 将 str 转换成 bytes
if all([python_3, isinstance(data, str)]):
data = bytes(data, encoding='utf-8')
self.sock.sendall(data)
return self.sock.recv(4096)
def close(self):
self.sock.close()
self.sock = None
self.__state = IDLE
return self.sock
def exit(self):
if self.__state != IDLE:
self.close()
return self._clients.pop(id(self))
def _address(self, side_address):
try:
pairs = getattr(self.sock, side_address)()
except Exception:
pairs = (None, None)
return pairs
def remote_address(self):
return self._address('getpeername')
def local_address(self):
return self._address('getsockname')
class ConnectNotReady(Exception):
pass
class SendNotReady(Exception):
pass
if __name__ == '__main__':
client = TCPClient(('127.0.0.1', 50007))
print(client.send('hello world!\r\n\r\n'))
print(client.send('hello world!\r\n\r\n'))
print(client.send('hello world!\r\n\r\n'))
client.exit()
with TCPClient(server_address=('127.0.0.1', 50007)) as client:
for i in range(3):
print(client.send('use for iteration inner with\r\n\r\n'))
for i in range(3):
with TCPClient(server_address=('127.0.0.1', 50007)) as client:
print(client.send('use for iteration\r\n\r\n'))
运行
# 启动服务 server.py
python wrapper_socket/server.py
# 运行客户端 client.py
python wrapper_socket/client.py
# 查看结果
b'hello world!\r\n\r\n'
b'hello world!\r\n\r\n'
b'hello world!\r\n\r\n'
b'use for iteration inner with\r\n\r\n'
b'use for iteration inner with\r\n\r\n'
b'use for iteration inner with\r\n\r\n'
b'use for iteration\r\n\r\n'
b'use for iteration\r\n\r\n'
b'use for iteration\r\n\r\n'
参考
- [x] socket.py部分源码
- [x] tornado部分源码
- [x] lib.http.client.py部分源码