Python用socket、多线程实现一对一聊天室

一、基于udp协议
1、通信原理
主机A -----发:hello----- 主机B
Hello由应用层往下包装:
主机A:
应用层:hello
传输层:将传输协议(UDP)与 hello 包装
网络层:将IP地址、传输协议(UDP)、hello 包装
链路层:将MAC(网卡地址)、IP地址、传输协议(UDP)、hello 包装
主机B:
链路层:MAC(网卡地址)、IP地址、传输协议(UDP)、hello
网络层:IP地址、传输协议(UDP)、hello
传输层:将传输协议、hello
应用层:hello (此时,主机B收到了hello,但是看不见的,此时我们用python写一个程序绑定主机A发过来的信息时指定的端口,从而收到这个数据包得到这个数据)

二、Socket简介
Socket是一种完成通过网络,使进程之间通信的方式。
用IP地址、协议、端口表示网络的进程,网络中进程通信就可以利用这个标志与其他进程进行交互

用python完成简单的发送:


#导入socket模块
from socket import *
 
#创建socket对象,AF_INET指ipv4协议,SOCK_DGRAM指udp
udpSocket=socket(AF_INET,SOCK_DGRAM)
 
#发送数据
def sendData:
while True:
sendMessage=input(“<<”)
udpSocket.sendto(sendMessage,(‘192.168.1.1’,8080)
sendData()

用python完成简单的接收:


from socket import *
udpSocket=socket(AF_INET,SOCK_DGRAM)
def recvData():
    while True:
        #创建接收对象,限定最大接收字节为1024
recvInfo=udpSocket.recvfrom(1024)
        Print(“>> %s”%recvInfo)
recvData()


三、多线程的引入
1、为什么使用多线程???

A send to B
以下面这个程序为例,当程序执行到<------部分时,此时程序跳转到循环接收信息的状态,此时A将无法发送消息给B

即使函数顺序换过来也是如此,当A在循环发发送信息给B的状态下时无法执行接收B的信息的。

#coding=utf-8
#导入socket模块
from socket import *
 
#发送数据
def sendData:
while True:
sendMessage=input(“<<”)
udpSocket.sendto(sendMessage,(‘192.168.1.1’,8080))
 
#接收数据
def recvData():
    while True:
        #创建接收对象,限定最大接收字节为1024
recvInfo=udpSocket.recvfrom(1024)
        Print(“>> %s”%recvInfo)
 
def main():
    #创建socket对象,AF_INET指ipv4协议,SOCK_DGRAM指udp
udpSocket=socket(AF_INET,SOCK_DGRAM)
 
recvData()  #<-------------
sendData()
 
if __name__ ==  “__main__”:
    main()

那么,有没有一种办法可以使接收信息与发送消息同时执行呢?使用多线程,正好可以解决此问题。

2、什么是多线程?
打个比方,在windows下运行用一个qq同时和n个qq好友进行聊天,这就是运用了多线程。

完整的局域网一对一的聊天室源码:


#coding=utf-8
from threading import Thread
from socket import *
 
#1.收数据,然后打印
def recvData():
     
    while True:
        recvInfo=udpSocket.recvfrom(1024)
        print(">>[%s:%s] to you %s:"%(str((recvInfo[1])[0]),str((recvInfo[1])[1]),recvInfo[0].decode("gb2312")))
        print("<<",end="")
     
 
#2.检测键盘输入,发数据
def sendData():
    try:
        while True:
            sendInfo=input("<<")
            udpSocket.bind((destIp,destPort))        #绑定ip、端口
            udpSocket.sendto(sendInfo.encode("gb2312"),(destIp,destPort))    #对数据进行转码发送
    except:
        print("发送失败!")
 
 
#给变量赋值none可以接收对象
udpSocket=None
destIp=""            #对方IP地址
destPort=0            #对方端口号
 
 
#多线程执行两个函数
def main():
 
    global udpSocket    #声明变量的作用域为全局作用域
    global destIp
    global destPort
 
    destIp=input("对方的IP:")
    destPort=int(input("对方的PORT:"))
 
    udpSocket=socket(AF_INET,SOCK_DGRAM)
    udpSocket.bind(("",1314))
 
    tr=Thread(target=recvData)
    ts=Thread(target=sendData)
 
    tr.start()
    ts.start()
 
    tr.join()
    ts.join()
 
if __name__ == "__main__":
    main()

猜你喜欢

转载自blog.csdn.net/lx1315998513/article/details/86611998