![94e84f845ff5a507f0d20cacabc2ad09.png](https://i-blog.csdnimg.cn/blog_migrate/f32c6716d2333b4c54ea13872d6a71c8.jpeg)
一、原理说明
框架代码说明:
#python通过线程和socket 最简单的方式实现TCP聊天功能import socketimport threadingip='127.0.0.1'port=7777s=socket.socket()#生成socket对象s.bind((ip, port))s.listen()def accp(): while True: newsock, clients = s.accept() ''' 执行到accept 方法处于阻塞状态 该方法生成 一个新的socket(保存在newsock) ,通过新socket 与客户端建立连接。 通过死循环,当执行到该处代码,程序阻塞,当TCP客户端发起tcp连接请求 ,程序执行到下面,并打印newsock 同时生成一个线程对象,调用recv 方法,(到此accp 第一次循环执行完毕,紧接着执行下一次循环并再此生成一个 新socke 等待其他客户端发过来的TCP连接) ,socket 的recv方法也是阻塞状态,该方法等待接收客户端发过来的数据 ,bytes类型 当 收到客户端发送的数据,recv函数的程序继续往下执行,打印data ,同时打印newsock的,打印这里只是为了验证 这里的socket和 accp函数里面第一次生成的socket是同一个对象,此时该函数执行完毕,同时进入下一次循环,执行到sock recv函数 的时候仍出于阻塞状态,直到TCP客户端发送信的数据过来。通过该方式 简单实现聊天的最初级版本功能 ''' print(newsock) threading.Thread(target=recv,args=(newsock,),name="recv").start()def recv(newsock): while True: data = newsock.recv(1024)#阻塞状态, print(data) print(newsock)accp()
版本二:
#TCP 的server端简单示例import socketimport threadingimport datetimeimport loggingformat="%(asctime)s-----%(process)s----%(thread)s-----%(threadName)s--日志消息--%(message)s "logging.basicConfig(format=format,level=logging.NOTSET)class ChatServer: def __init__(self,ip='127.0.0.1',port=9999): self.sock=socket.socket() self.addr=ip,port self.event = threading.Event() self.newsocks={}#保存 newsocket 和tcp客户端连接信息。后面通过循环close socket self.lock=threading.Lock() def start(self): self.sock.bind(self.addr) self.sock.listen() threading.Thread(target=self.accept).start() def accept(self): while not self.event.is_set():#当event 是false执行 newsocket,clientinfo=self.sock.accept() with self.lock: self.newsocks[clientinfo]=newsocket threading.Thread(target=self.recv,args=(newsocket,clientinfo),name="recv").start() def recv(self,newsocket,clientinfo): while not self.event.is_set(): try: data=newsocket.recv(1024) except: data=b'' print(data) if data.strip()==b'quit' or data.strip()==b'':#tcp客户端 软件如果直接点击断开 会生成一个空byets 这里防止出现异常 with self.lock: self.newsocks.pop(clientinfo) newsocket.close() break msg="{:%Y-%m-%d %H:%M:%S}[{}--{}-{}]".format(datetime.datetime.now(), *clientinfo,data.decode()) with self.lock: for s in self.newsocks.values(): s.send(msg.encode())## 将str类型转成bytes 网络中传输的都是bytes类型 ##data.decode()将受到的bytes类型转换成字符串 def stop(self): self.event.set() keys=[] with self.lock: keys=list(self.newsocks.values()) self.newsocks.clear() for soc in keys: soc.close() self.sock.close()cs = ChatServer()cs.start()while True: cmd=input(">>").strip() if cmd=="q": cs.stop() break logging.info(threading.enumerate())该程序还有bug 就是newsocket.recv(1024) 处可能会因为网络原因产生异常 可以通过 try except 处理。可以继续优化备注 这里TCP 客户端是通过 tcp/udp调试工具模拟