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()
  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值