gpt4 book ai didi

python - 使用线程在 UDP 聊天中使用一个套接字

转载 作者:太空宇宙 更新时间:2023-11-03 16:01:30 24 4
gpt4 key购买 nike

我正在研究 UDP 聊天,它应该只使用一个套接字来监听并能够随时发送消息。例如,我将完成聊天程序,我将第一次打开它,然后第二次,我必须能够通过 UDP 从两个程序进行通信,简单地说,每个程序只有一个打开的套接字。

我的两个线程是用于监听的,一个是守护线程,因为我想让它不停地监听新消息,另一个线程是发送消息,就像普通线程一样。

首先,我的问题是我的线程看起来互相阻塞,因为如果我运行程序,我只能从启动的第一个线程获得输出。

第二个问题是我不确定我的发送函数或者整个类是否写得正确,或者是否有遗漏或不正确的地方。

提前致谢。顺便说一句,我是 python 新手,我正在使用 python 3,只是为了说清楚。

import socket
import threading
import logging
import time
from sys import byteorder


class Sending():
def __init__(self, name, tHost, tPort):
self.name = name
self.host = tHost
self.port = tPort

def set_name(self, name):
self.name = name

def send(self, name, tHost, tPort, msgType, dgramSize):
logging.debug('Starting send run')
message = input('Enter message: ')
data = bytearray()
data.extend( (name.encode('utf-8'), message.encode('utf-8'), msgType.to_bytes(1, byteorder = 'little')) )
#data.extend(message.encode(encoding='utf_8'))
self.sock.sendto(bytearray(data), (tHost, tPort))

def run(self):

th2 = threading.Thread(name = 'send', target=self.send('username', 'localhost', 8001, 1, 1400))
th2.start()

class Receiving():
def __init__(self, host, port):
self.host = host
self.port = port

def create_socket(self, host, port):
logging.debug('Starting socket')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((host, port))
#print ('socket ready')
time.sleep(5)
while True:
data, addr = sock.recvfrom(1500)
print('Prijata:' + data + addr)

def run(self):

th1 = threading.Thread(name = 'rec', target=self.create_socket('localhost', 8000))
th1.setDaemon(True)
th1.start()

if __name__ == '__main__':
#print ('running')
rec = Receiving('localhost', 8000)
send = Sending('username', 'localhost', 8001)
send.run()
rec.run()

最佳答案

恭喜您了解 Python!看起来您正在使用 Python 3,在以后的问题中,如果您明确说明您正在使用哪个版本,将会很有帮助,因为某些代码(包括此代码!)中存在轻微但破坏程序的不兼容性。

我在您的程序中发现了一些错误:

  • 最重要的问题 - 正如 Trevor Barnwell 所说,您没有非常正确地调用 threading.Threadtarget= 参数必须是可调用对象(即函数),但在本例中它应该只是对函数的引用。如果您向函数 self.create_socket(host, port) 添加括号,如上面所示,它实际上会立即运行该函数。正如 Trevor 所解释的,您的 Sending.send() 方法被提前调用,但 Receiving 中也存在类似的错误。由于 Receiving.create_socket() 创建了一个无限循环,因此它永远不会返回程序执行。虽然控制台输出对用户来说看起来是正确的,但实际的程序执行从未使其在单独的线程中运行监听器。

  • bytearray.extend() 接受一个可迭代的整数,您现在传递的是一个字节对象的元组。

  • Sending.send() 中,您调用 self.sock,但从未为 self.sock 分配值,因此它失败了。

  • Sending.run() 仅运行 Sending.send() 一次。用户输入完毕后,立即退出,因为程序已经结束了。

如果您正在寻找适合经验丰富的程序员的基于项目的深入 Python 介绍(包括与基本套接字问题非常相似的练习,以及另一个关于线程的练习),我强烈建议您查看 Wesley Chun 的《核心 Python 应用程序编程》。最新版本(第 3 版)包含大量 Python 2 代码,但只需读者做一些小工作即可轻松移植到 Python 3。

我尝试尽可能少地修改您的代码以使其正常工作,如下:

import socket
import threading
import logging
import time


class Sending():
def __init__(self, name, tHost, tPort, target):
self.name = name
self.host = tHost
self.port = tPort
self.target_port = target
self.sock = self.create_socket()

def create_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((self.host, self.port))
return sock

def set_name(self, name):
self.name = name

def send_loop(self):
while True:
logging.debug('Starting send run')
message = input('Enter message: ')
data = bytearray()
data.extend(message.encode('utf-8'))
self.sock.sendto(bytearray(data), (self.host, self.target_port))

def run(self):
th2 = threading.Thread(name='send', target=self.send_loop)
th2.start()


class Receiving():
def __init__(self, host, port):
self.host = host
self.port = port

def create_socket(self):
logging.debug('Starting socket')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((self.host, self.port))
print ('socket ready')
time.sleep(5)
while True:
data, addr = sock.recvfrom(1500)
print('\nPrijata:' + data.decode('utf-8') + str(addr))

def run(self):
th1 = threading.Thread(name='rec', target=self.create_socket)
print("Made it here")
th1.daemon = True
th1.start()
return

if __name__ == '__main__':
print('running')
rec = Receiving('localhost', 8000)
send = Sending('username', 'localhost', 8001, 8000)
rec.run()
send.run()

关于python - 使用线程在 UDP 聊天中使用一个套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40305424/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com