Python 多线程不适用于双向udp通信

Python 多线程不适用于双向udp通信,python,udp,python-multithreading,Python,Udp,Python Multithreading,我正在尝试使用多线程编写双向UDP通信,但它在发送两条消息后崩溃。另外,我是线程新手,所以请在此发布您的解决方案。 谢谢 服务器端: import threading from threading import Thread import socket from socket import * import time import pymongo from datetime import datetime from time import ctime #broadcast works for t

我正在尝试使用多线程编写双向UDP通信,但它在发送两条消息后崩溃。另外,我是线程新手,所以请在此发布您的解决方案。 谢谢

服务器端:

import threading
from threading import Thread
import socket
from socket import *
import time
import pymongo
from datetime import datetime
from time import ctime
#broadcast works for this program
import netifaces
import os
import re
import struct
class cont():


    def get_msg(self):
        UDP = "192.168.1.27"
        port = 4343
        address = UDP, port
        self.sock = socket(AF_INET, SOCK_DGRAM)
        self.sock.bind(address)
        while True:
            r = self.sock.recvfrom(1000)
            print("controller1: %s" % (r[0]))
            reply = input('Main controller  : ')
            client_address = r[1]
            self.sock.sendto(bytearray(reply, "utf-8"), client_address)
            t2 = threading.Thread(target=self.get_msg, args=(reply,))
            t2.start()
if __name__=='__main__':
    c=cont()
    #c.broad(msg="")
    c.get_msg()
客户端:

UDP=""
port=4343
address=UDP,port
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while(True):
    msg=input("Controller1")
client.sendto(bytearray(msg,"utf-8"),address)
reply=client.recvfrom(1000)
recved=str(reply)
print("Main Controller:% s" % recved))
所需输出:
这是我为与我的机器人通信而设计的TCP类,可以很容易地修改为UDP。可能看起来有很多代码,但这是在不阻塞主程序的情况下实现“可靠”“双向”通信所需要的。我使用进程而不是线程,因为python中的线程由于全局解释器锁而不是“真正的”线程

import socket
from multiprocessing import Process, Queue, Event, Value
import traceback

class SocketComm(object):
    def __init__(self,port):
        self.address = ""
        self.otherAddress = object
        self.port = port
        self.finished = Value("b", True)
        self.inbox = Queue()
        self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.getMessagesProcess = Process(target=self.getMessages)
        self.getMessagesProcess._stop_event = Event()
        self.getMessagesProcess.daemon = True

        self.connected = False
        self.timeout = 3
        return

    def setupLine(self, addr):
        self.address = addr
        if self.address is "": #i.e. server on raspberry pi
            try:
                self.connection.settimeout(self.timeout)
                self.connection.bind((self.address, self.port))
                print("binding with port: " + str(self.port))
                self.connection.listen(1)
                self.connection, self.otherAddress = self.connection.accept()
                print("connected to client at: " + self.otherAddress[0])
            except socket.error as e:
                print(str(e))
                return False
        else:
            try:
                #print("connecting to port: " + str(self.port))
                self.connection.connect((self.address, self.port)) # i.e. client
                print("connected to server")
            except socket.error as e:
                #print(str(e))
                return False

        self.getMessagesProcess.start()
        self.connected = True
        self.finished.value = False
        print("inbox at: " + str(id(self.inbox)))
        return True

    def sendMessage(self, msg):
        try:
            self.connection.send(str.encode(msg))
            #print("sent: " + str(msg))
        except Exception as e:
            pass
            #print(str(e))
            #traceback.print_exc()
            #print("exception caught.")
        return

    def getMessages(self):
        #print("getting messages now")
        self.connection.settimeout(1)
        while(not self.finished.value):
            #print("checking inbox")
            #print("inbox length: " + str(len(self.inbox)))
            try:
                received = self.connection.recv(1024)
                decoded = received.decode('utf-8')
                if len(decoded) > 0:
                    if(decoded == "end"):
                        self.finished.value = True
                    else:
                        self.inbox.put(decoded)
                        print("received: " + str(decoded))
            except socket.error as e:
                if(type(e).__name__ == "timeout"):
                    pass
                else:
                    print("endpoint closed.")
                    self.finished.value = True
        return

    def closeConnection(self):
        if(self.connected):
            self.finished.value = True
            self.getMessagesProcess._stop_event.set()
            self.sendMessage("end")
            try:
                self.getMessagesProcess.join()
            except:
                print("process already finished.")
            self.connection.close()
        return



##
##if(__name__ == "__main__"):
##    robotClient = SocketComm(5555)
##    robotClient.setupLine("127.0.0.1")
##    while(robotClient.finished.value == False):
##        val = input("enter something: ")
##        if(len(val) > 0):
##            robotClient.sendMessage(val)
##
##
##if(__name__ == "__main__"):
##    try:
##        robotServer = SocketComm(5555)
##        print("waiting for client to connect...")
##        robotServer.setupLine("")
##        print("connected!")
##        while(robotServer.finished.value == False):
##            val = input("enter something: ")
##            if(len(val) > 0):
##                robotServer.sendMessage(val)
##    except:
##        pass
##    finally:
##        robotServer.closeConnection()
##        sys.exit(0)

get\u msg
不需要参数
reply
。您想要实现什么?我想要从客户端接收消息,然后像双向通信一样向其发送返回回复。您在每个线程的每次迭代中都启动一个新线程?线程之间没有阅读协调。在if main中,您在哪里调用您的类?我的整个项目都使用了多线程,所以我对这部分代码印象深刻,所以我在一个端口监听客户机并将数据存储在数据库中,另一个端口是双向通信。双向或客户端存储线程都可以工作。它们都不在一起工作在代码的底部是一个完全可执行的服务器和客户机示例-你的意思是什么,我主要在哪里称呼它?你可以继续使用线程,但是在你的程序中,这个类作为一个独立的模块开箱即用。我明白你为什么问了,我忘了我从
Communicate
将这个类重命名为
SocketComm
,当我这样做时,我没有在注释的示例中重构类名。现在已经修复了。在robotclient.setup(“”)中,我们在哪里提到端口?Gah,我在注释示例中忘了做的另一个编辑。如果您查看SocketComm
\uuuuu init\uuuu
函数,它就是在这里使用端口的。请稍候,我将更新示例。
import socket
from multiprocessing import Process, Queue, Event, Value
import traceback

class SocketComm(object):
    def __init__(self,port):
        self.address = ""
        self.otherAddress = object
        self.port = port
        self.finished = Value("b", True)
        self.inbox = Queue()
        self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.getMessagesProcess = Process(target=self.getMessages)
        self.getMessagesProcess._stop_event = Event()
        self.getMessagesProcess.daemon = True

        self.connected = False
        self.timeout = 3
        return

    def setupLine(self, addr):
        self.address = addr
        if self.address is "": #i.e. server on raspberry pi
            try:
                self.connection.settimeout(self.timeout)
                self.connection.bind((self.address, self.port))
                print("binding with port: " + str(self.port))
                self.connection.listen(1)
                self.connection, self.otherAddress = self.connection.accept()
                print("connected to client at: " + self.otherAddress[0])
            except socket.error as e:
                print(str(e))
                return False
        else:
            try:
                #print("connecting to port: " + str(self.port))
                self.connection.connect((self.address, self.port)) # i.e. client
                print("connected to server")
            except socket.error as e:
                #print(str(e))
                return False

        self.getMessagesProcess.start()
        self.connected = True
        self.finished.value = False
        print("inbox at: " + str(id(self.inbox)))
        return True

    def sendMessage(self, msg):
        try:
            self.connection.send(str.encode(msg))
            #print("sent: " + str(msg))
        except Exception as e:
            pass
            #print(str(e))
            #traceback.print_exc()
            #print("exception caught.")
        return

    def getMessages(self):
        #print("getting messages now")
        self.connection.settimeout(1)
        while(not self.finished.value):
            #print("checking inbox")
            #print("inbox length: " + str(len(self.inbox)))
            try:
                received = self.connection.recv(1024)
                decoded = received.decode('utf-8')
                if len(decoded) > 0:
                    if(decoded == "end"):
                        self.finished.value = True
                    else:
                        self.inbox.put(decoded)
                        print("received: " + str(decoded))
            except socket.error as e:
                if(type(e).__name__ == "timeout"):
                    pass
                else:
                    print("endpoint closed.")
                    self.finished.value = True
        return

    def closeConnection(self):
        if(self.connected):
            self.finished.value = True
            self.getMessagesProcess._stop_event.set()
            self.sendMessage("end")
            try:
                self.getMessagesProcess.join()
            except:
                print("process already finished.")
            self.connection.close()
        return



##
##if(__name__ == "__main__"):
##    robotClient = SocketComm(5555)
##    robotClient.setupLine("127.0.0.1")
##    while(robotClient.finished.value == False):
##        val = input("enter something: ")
##        if(len(val) > 0):
##            robotClient.sendMessage(val)
##
##
##if(__name__ == "__main__"):
##    try:
##        robotServer = SocketComm(5555)
##        print("waiting for client to connect...")
##        robotServer.setupLine("")
##        print("connected!")
##        while(robotServer.finished.value == False):
##            val = input("enter something: ")
##            if(len(val) > 0):
##                robotServer.sendMessage(val)
##    except:
##        pass
##    finally:
##        robotServer.closeConnection()
##        sys.exit(0)