用多线程实现多用户同时收发的简单socket服务端

简单的socket代码和多线程练习


用socket服务端和多线程实现可以连接多个客户端并同时收发的功能。

这里要用到socket 和 threading

所以,记得:

import socket, threading


一、创建socket服务端

首先,按正常操作,创建一个socket,选择ipv4和数据流:

socketServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

通过socket模块获取本地ip,并绑定ip和端口号,设置监听数量
socketServer.bind((socket.gethostbyname(socket.gethostname()),
8080))
socketServer.listen(5)      #这里监听数量和创建的接收线程数应保持一致 

然后设置两个全局变量,以便线程中的得到的客户端信息和ip传出,方便选择发送信息

global Cilents, addrips
Cilents = []
addrips = [] 二、多线程

考虑到多个客户端连接,就需要把等待连接、接收信息、发送信息其中两个个丢到多线程中,我选择把发送信息放在主线程,并在等待连接的进程中再创建接收信息的进程:

def waitFaccept():
    while True:
        Cilent1, addrip = socketServer.accept()
        Cilents.append(Cilent1)
        addrips.append(addrip)
        for i in range(len(addrips)):
            print('%d:%s' % (i+1, addrips[i][0]))
        while threading.active_count() > 6:
            pass
        t = threading.Thread(target=receive, args=(Cilent1, addrip))
        t.start()


def receive(socketServer, addrip):
    while True:
        try:
            content = socketServer.recv(1024)
            if len(content) != 0:
                print('收到客户端%d号%s的消息:%s' % (Cilents.index(socketServer) + 1, addrip[0], content.decode('utf-8')))
        except ConnectionResetError:
socketServer.close()
            print('与%s的连接已断开!' % addrip[0])
            addrips.remove(addrip[0])
            Cilents.remove(socketServer)
            for i in range(len(addrips)):
                print('%d:%s' % (i+1, addrips[i][0]))
            break

threading的用法就不用多说了吧,传函数和参数,然后start就搞定了


三、主线程后续


然后接着写主线程部分的内容:

threading.Thread(target=waitFaccept).start()
while True:
    if threading.active_count() > 2:
        break

# 接收数据
while True:
    while True:
        for i in range(len(addrips)):
            print(' %d : %s' % (i+1, addrips[i][0]))
        setnum = input('请输入客户端编号:')
        try:
            setnum = int(setnum) - 1
        except ValueError:
            print('%s error\r\n请输入一个数字!' % setnum)
            continue
        if setnum < len(Cilents) and setnum >= 0:
            break
        else:
            print('请输入范围内的编号!!', end='\r')
    content = input('给%s发送的内容:' % (addrips[setnum][0]))
    # Cilent1.sendall(str.encode(content))
    try:
        Cilents[setnum].sendall(content.encode('utf-8'))
    except ConnectionResetError:
        if Cilents[setnum] in Cilents:
            Cilents.remove(Cilents[setnum])
            addrips.remove(addrips[0][0])

Cilents[setnum].close()

写完需要丢到多线程中的等待连接和接收数据函数后,启动等待连接函数的线程,用while阻塞主线程,利用threading.active_count()的方法获取线程数来判断是否有客户端连接进来。等待客户端连接之后继续运行主线程,根据global中储存的客户端,就可以愉快的选择发送信息了。PS:后面的细节部分写的不是特别好,如果接收到数据命令行会显得很乱,不过并不影响发送。

如果不想研究可以自己下载玩一玩:https://download.csdn.net/download/an195/10472725





你可能感兴趣的:(python,多线程,socket服务端)