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

时间:2018-08-15 19:20:49

标签: python udp python-multithreading

Output at console server

我正在尝试使用多线程编写双向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))

需要的输出:

Server Console:

Client:b'hello'
Server:b'hi

Client Console:

Client: b'hello'
Server : (b'hi',('ip',port)

1 个答案:

答案 0 :(得分:0)

这是我为与机器人进行通信而创建的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)