python 实现 udp socket 编程的多线程问题


希望实现以下功能:
在点击“启动服务器”,即执行start函数时,开启监听线程,监听线程会用recvfrom()函数来监听数据报的到来。但是如果没有数据报过来,则其会阻塞在recvfromm()上。但是希望在没有数据报来的时候,可以继续主进程(会发送数据报的进程)的执行。

求问怎么做??

具体两个函数如下:(给出了前面主要的函数,剩下的一些省略了)
from tkinter import *
from time import sleep
from UserTable import *
from RoomTable import *
from ServerReceive import *
from socket import *
import pickle
import re
import string
import time
import threading
import pdb

用于建立服务端界面,建立监听线程,并处理本地命令

root = Tk()
root.geometry("600x400")
root.title("服务器端")

userroot = UserInfo(0, '', '', 0)
userTable = UserTable(userroot, None, 0) #用户列表
roomTable = RoomTable( ) #竞拍室列表
InRoom = None
text_contents=''
host = '127.0.0.1'
port =7890
nums = string.digits

发送按键对应的函数

def Send():
text_contents = text.get()
listbox.insert(END, text_contents)
text.delete(0,END)
cmd_choice(text_contents)

启动按键对应的函数,服务器端启动

def Start():
try:


 global server
  server = socket(AF_INET, SOCK_DGRAM)      #启动服务端socket,默认端口7890
  server.bind((host, port))

  listbox.insert(END, "服务器端启动" )
  #pdb.set_trace()
  serverrec = ServerReceive(server, listbox, userTable, roomTable)
  #pdb.set_trace()
  serverrec.start()            #建立监听线程???
  serverrec.join()
except:
  Exception, e
  print(e)

退出按键对应的函数.服务器端退出

def Exit():
SendMsg("/msg 【系统消息】 服务器关闭!")


 exit()

进行命令匹配的函数

def cmd_choice(text_contents):
m=re.match("/msg ", text_contents)
if m: #群发消息
SendMsg(text_contents)
else:
m=re.match("/list", text_contents) #列出某竞拍室情况
if m:
List()
else:
m=re.match("/kickout ", text_contents) #将某竞拍者踢出拍卖室
if m:
Kickout(text_contents)
else:
m=re.match("/opennewauction ", text_contents) #开通新竞拍室
if m:
Open(text_contents)
else:
m=re.match("/auctions", text_contents) #列出所有竞拍室情况
if m:
Auction()
else:
m=re.match("/enter ", text_contents) #加入某竞拍室
if m:
Enter(text_contents)
else:
m=re.match("/leave", text_contents) #离开某竞拍室
if m:
Leave()
else:
m=re.match("/close ", text_contents) #关闭某竞拍室
if m:
Close(text_contents)
else: #其他格式错误命令,弹出警告框??
listbox.insert(END, "\t命令输入错误!")

命令/msg [bidderID],群发和向指定用户发送消息

def SendMsg(text_contents):
lenmsg = len(text_contents)
if lenmsg == 4 or lenmsg == 5: #命令中没有发送内容,警告
listbox.insert(END, "未输入发送消息的内容!\n" )
return


 i = 7
    if text_contents[5] == "[" and text_contents[6] in nums:  #对某一用户发送消息 查找用户ID
        while text_contents[i] in nums:
                i=i+1
        if text_contents[i] != "]":
                listbox.insert(END, "\t命令输入错误!" )         #未输入用户ID,提示错误
                return
        ID = text_contents[6:i]                               #提取用户ID
        temp = userTable.findUser(ID)
        if temp :                       #在用户列表中找到该用户??
            if i+1 == lenmsg:
                listbox.insert(END, "未输入发送消息的内容!\n" )         #命令中没有发送内容,警告
                return
            message = text_contents[i+1:] + "\n"               #提取发送内容
            try:                                                   #发送内容???
                server.sendto(message, temp.addr, temp.port)
            except:
                Exception,e 
                print (e)

        else:
            listbox.insert(END, "没有该用户!\n" )              #未在用户列表中找到该用户,警告
            return
    else:                                                     #对所有用户群发消息
        message = text_contents[i+1:] + "\n"
        temp = userTable.root
        while temp.next != None:                              #遍历用户列表并发送消息
            temp = temp.next
            try:                                                   #发送内容???
                server.sendto(message, temp.addr, temp.port)
            except:
                Exception, e 
                print (e)

命令/list,列出某一竞拍室参加竞拍者的情况(必须已进入某一竞拍室)

def List():

————————————————————————————————————————————
监听线程如下:
import re
import string
import threading
import pickle
from tkinter import *
from socket import *
from UserTable import *
from RoomTable import *
import pdb

类ServerReceive 网络拍卖行服务端监听接收线程类

用于监听并接收客户端发送过来的数据包,并进行相应的处理

class ServerReceive(threading.Thread):


 server = socket(AF_INET, SOCK_DGRAM) 
addr=''
port=0
ADDR=(addr,port)
recvStr=''
newStr=''
root=UserInfo(0, '', '', 0)
userList = UserTable(root, None, 0)             #用户列表
roomTable = RoomTable()         #竞拍室列表
bufsize=512
user = UserInfo(0, '', '', 0)                #用户信息
room = RoomInfo('', 0)                 #竞拍室信息
bidderID = 1                    #分配的用户ID    
listbox = None

def __init__(self, server, listbox, userList, roomTable):
    super().__init__()
    self.server = server
    self.listbox = listbox                   #消息接收区域     
    self.userList = userList
    self.roomTable = roomTable


#启动监听并接收数据包,并对数据包进行处理
def run(self): 
    pdb.set_trace()
    #i=0
    while True:
        #if i >= 1:
            #break
        try:
            self.recvStr, self.ADDR = self.server.recvfrom(self.bufsize)        #提取数据报内容,用户IP地址,端口号
            self.user = self.userList.findUser(self.addr, self.port)                        #在用户列表中查找该用户信息
            #socket.settimeout(self.server)
            self.recvStr = self.recvStr.decode('gb2312')
            #i+= 1
            m=re.match("/login ", self.recvStr)           
            if m:                                      #登录服务器
                self.Login(self.recvStr,self.ADDR)
            else: 
                m=re.match("/exit", self.recvStr)      #退出
                if m:
                    self.Exit()
                else:
                    if user == None:                    #未登录(此时不允许输入除登录、退出之外的命令)
                        self.NoLogin()                       
                    else:
                        m=re.match("/auctions", self.recvStr)    #列出所有竞拍室情况
                        if m:
                            self.Auctions()
                        else:
                            m=re.match("/list", self.recvStr)      #列出某竞拍室情况
                            if m:
                                self.List()
                            else:
                                m=re.match("/join ", self.recvStr)      #加入某竞拍室
                                if m:
                                    self.Join(self.recvStr)
                                else:   
                                    m=re.match("/bid ", text_contents)  #出价
                                    if m:
                                        self.Bid(self.recvStr)
                                    else:
                                        m=re.match("/leave", self.recvStr)  #离开某竞拍室
                                        if m:
                                            self.Leave()
                                        else:                                   #其他格式错误命令
                                            self.ErrorCom()  
        except:
            Exception,e
            print(e)

#命令格式错误
def ErrorCom(self):
    error = "命令输入错误!\n"
    try:                                                   #发送内容???
        self.server.sendto(error, self.addr, self.port)
    except:
        Exception, e 
        print (e)

#命令/login bidderName,用bidderName登录服务器。服务方给该用户分配一个唯一标识bidderID
def Login(self, recvStr,ADDR1):
    pdb.set_trace() 
    if len(recvStr) == 7:                   #命令不包含用户名
        newStr = "未输入用户名!\n"        
    else:
        name = recvStr[7:]
        print(name)
        if self.userList.findUser1(name) == None and self.user == None:
            self.user = UserInfo(self.bidderID, name, self.addr, self.port)             #加入新用户信息
            self.userList.addUser(self.user)    

            self.listbox.insert(END, "用户 " + name + " 连接成功! "  + str(ADDR1)+ "\n")
            self.bidderID+= 1
            newStr ="【系统消息】 您好,"+ name + ",欢迎来到网络拍卖行" + "!  您的用户ID: " + str(self.bidderID) + "\n" #返回欢迎信息
        else:
            if self.userList.findUser(self.addr, self.port)!= None:                         #该IP地址和端口已经登录过用户    
                newStr = "不能登录多个用户!\n"
            else:
                if self.userList.findUser(name)!= None:                                    #用户列表中已存在该用户名
                    newStr = "不能重复登录!\n";
                    try:                                                   #发送内容???
                        self.server.sendto(newStr, self.addr, self.port)
                    except:
                        Exception, e
                        print (e)

python socket udp

Became 11 years, 6 months ago

Your Answer