在TCP server中使用多线程

目前,我所实现的TCP server服务能力都很差,根本无法同时与多个客户端进行交互,只有处理完一个客户端的交互以后才能使用accept等待下一个客户端的连接。

本篇,我将使用多线程技术,在通过accept获得一个socket文件后,启动一个多线程来专门处理这个客户端的数据传输。

1. 服务端代码

import socket
import threading


def worker(client):
    while True:
        data=client.recv(1024)    #把接收的数据实例化
        if len(data) == 0 or data == None:
            break
        print(data.decode(encoding='utf-8'))
        client.send('收到数据'.encode(encoding='utf-8'))


def start_server(port):
    HOST = '0.0.0.0'
    PORT = port
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #定义socket类型,网络通信,TCP
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST,PORT))   #套接字绑定的IP与端口
    s.listen(1)           #开始TCP监听
    while True:
        conn, addr = s.accept()   #接受TCP连接,并返回新的套接字与IP地址
        print('Connected by',addr)          #输出客户端的IP地址
        t = threading.Thread(target=worker, args=(conn, ))
        t.start()


if __name__ == '__main__':
    start_server(8801)

在服务端,我使用while实现了无限循环,在循环里使用accept接受TCP连接,获得连接后,这个连接何时将全部数据发送给服务端是未知的,如果一直处理这个连接,那么其他的连接就无法处理,因为在服务端,代码无法执行到下一次accept。使用了多线程以后,情况就不同了,每个TCP连接使用一个线程来处理,那么主线程就可以再次执行到accept这行代码上,不受任何操作的阻塞影响。

2. 客户端代码

import os
import time
import socket

def start_client(addr, port):
    PLC_ADDR = addr
    PLC_PORT = port
    s = socket.socket()
    s.connect((PLC_ADDR, PLC_PORT))
    count = 0
    while True:
        msg = '进程{pid}发送数据'.format(pid=os.getpid())
        msg = msg.encode(encoding='utf-8')
        s.send(msg)
        recv_data = s.recv(1024)
        print(recv_data.decode(encoding='utf-8'))
        time.sleep(3)
        count += 1
        if count > 20:
            break

    s.close()

if __name__ == '__main__':
    start_client('127.0.0.1', 8801)

客户端不需要做什么改变,在代码里,每次发送完消息后,都会sleep 3秒钟,一共发送20次,这样,就有足够的时间启动多个client来测试服务端是否有能力同时处理多个客户端的请求了。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案