上一篇我们通过线程锁实现了一个简单的并发写日志功能,该篇我们通过socket来实现一个写日志的程序,代码如下:
socket服务端
import selectors
import socket, time
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept()
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
lastPre = ''
def read(conn, mask):
global lastPre
try:
data = conn.recv(1024)
except ConnectionResetError as e:
print('检测到客户端在发送数据时异常退出,服务端关闭该连接', conn)
sel.unregister(conn)
conn.close()
if data:
data = data.decode('utf-8')
dataList = data.strip(';').split(';')
if lastPre != '':
dataList[0] = lastPre + str(dataList[0])
if data.endswith(';'):
lastPre = ''
else:
lastPre = str(dataList[-1])
dataList = dataList[:-1]
for d in dataList:
# 写日志功能自己实现,日志是否写成功不需要返回,所以我们注释掉try..except段代码
time.sleep(1)
text = d + " is completed successfully"
print(text)
#try:
#conn.send(bytes(text, encoding='utf-8'))
#except ConnectionResetError as e:
#print('服务端发送数据时客户端异常退出,服务端关闭该连接', conn)
#sel.unregister(conn)
#conn.close()
else:
print('客户端正常退出,服务端关闭该连接', conn)
sel.unregister(conn)
conn.close()
def server():
sock = socket.socket()
sock.bind(('localhost', 1234))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
while True:
events = sel.select()
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
if __name__ == '__main__':
server()
socket.send只能发送bytes类型的数据,所以我们需要在服务端自己按照预定的规则来处理数据,比如我们split(‘;’)。
socket.sendfile可以一个文件对象。
另外socket默认使用tcp协议,即SOCK_STREAM,也可以改为udp协议,即SOCK_DGRAM。
具体细节,大家多参考官方文档
socket客户端
import socket
def client():
addr = ('127.0.0.1', 1234)
s = socket.socket()
s.connect(addr)
for i in range(30):
text = "测试" + str(i) + ";"
s.send(bytes(text, encoding="utf-8"))
#data = s.recv(1024)
#print(data)
def mulClient():
socks = []
addr = ('127.0.0.1', 1234)
for i in range(10):
socks.append(socket.socket())
for s in socks:
s.connect(addr)
for i in range(10):
for s in socks:
text = "Socket"+ str(socks.index(s)) + "-" + str(i)+ ";"
s.send(bytes(text, encoding="utf-8"))
#data = s.recv(1024)
#print(data)
if __name__ == '__main__':
mulClient()