美文网首页
基于UDP的简单聊天-socket

基于UDP的简单聊天-socket

作者: 沿哲 | 来源:发表于2020-10-26 10:20 被阅读0次

    最近学习python 的socket模块,想实现两台不同主机的聊天

    通信主机1的配置:

    • win10
    • python 3.6
    • 通信ip:在cmd运行ipconfig后 无线局域网WLAN处的IPv4

    通信主机2的配置:

    • win10
    • python 3.8
    • 通信ip:在cmd运行ipconfig后 无线局域网WLAN处的IPv4

    实现效果:主机1、2基于UDP的聊天

    • 主机1、2均为双工,运行开始时双方均开启发送和接收两个线程
    • 主机1发消息结束[主机1发送消息的线程结束],主机2不再接收[主机2的接收线程结束];
      此时主机1还可以接收2的消息;
      此时若主机2发消息结束[主机2发送线程结束],主机1不再接收[主机1接收线程结束];
      socket结束

    效果图

    分别从两台主机的运行窗口处截图[两台主机时间上差个2秒,主机2快2秒。所以收发消息基本时间一致]


    主机1 主机2

    代码如下

    import socket
    import threading
    import tkinter as tk
    import time
    import inspect
    import ctypes
    
    
    mywspn=('10.**.***.**',8800)
    
    #######停止线程的模块,来源于网上
    def _async_raise(tid, exctype):
        """raises the exception, performs cleanup if needed"""
        tid = ctypes.c_long(tid)
        if not inspect.isclass(exctype):
            exctype = type(exctype)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            # """if it returns a number greater than one, you're in trouble,
            # and you should call it again with exc=NULL to revert the effect"""
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")
     
    def stop_thread(thread):
        _async_raise(thread.ident, SystemExit)
    
    
    ########接收消息
    def receive(s):
    
        print('re start')
        while True:
            data,add=s.recvfrom(1024)
            data=data.decode()
            if data=='bye':
                break
            else:
                print('from',add,'say:',data,'time is', time.asctime( time.localtime(time.time()) ))
        stop_thread(t2)#停止接收消息的线程
        if t1.isAlive():
            print('t1 alive')
        else:
            print('socket closed')
            s.close()
            
    
    #######发送消息     
    def send(s):
        print('send start')
       # inp=input('发送:')
        
        while True:
            inp=mygui("Enter data")
            print('I say:',inp,'time is', time.asctime( time.localtime(time.time()) ))
            s.sendto(inp.encode(),mydell) #注意逻辑,先send再break
            if inp=='bye':
                s.sendto('I am offline'.encode(),mydell) 
                break
        stop_thread(t1) #停止发送消息的线程       
        if t2.isAlive():
            print('t2 alive')
        else:
            print('socket closed')
            s.close()
    
    
    #发送消息的GUI界面
    def mygui(prompt=""):
    
        root = tk.Tk()
        tk.Label(root, text=prompt).pack()
        entry = tk.Entry(root)
        entry.pack()
        result = None
        def callback(event):
            nonlocal result
            result = entry.get()
            root.destroy()
        entry.bind("<Return>", callback)
        root.mainloop()
        return result
    
    
    s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.bind(('',8888))
    
    t1=threading.Thread(target=send,args=(s,))
    t2=threading.Thread(target=receive,args=(s,))
    t1.start()
    t2.start()
    
    

    相关文章

      网友评论

          本文标题:基于UDP的简单聊天-socket

          本文链接:https://www.haomeiwen.com/subject/bwxomktx.html