tcp port numbers reused出现原因_python socket(tcp 线程)实现简单聊天室

94e84f845ff5a507f0d20cacabc2ad09.png

一、原理说明

框架代码说明:

#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调试工具模拟
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值