簡體   English   中英

處理雙端隊列時接收UDP消息

[英]Receiving UDP message while processing a deque

為了解決這個問題 ,我正在嘗試簡化問題。 假設我有一個接收器在偵聽TCP和UDP消息。 它將接收幾個字符串,將它們附加到雙端隊列,並在收到"finish"消息后,將開始處理雙端隊列。

如果收到UDP消息,則需要停止處理,刪除雙端隊列的最后一項,然后繼續處理。

from collections import deque

host = commands.getoutput("hostname -I")
port = 5005
backlog = 5
BUFSIZE = 4096
q = deque()


def read_tcp(s):
    conn, addr = s.accept()
    print('Connected with', *addr)
    while 1:
        data = conn.recv(BUFFER_SIZE)
        if not data: break
        print "received data:", data
        conn.send(data)  # echo
    conn.close()
    if (data == 'finish'):
        processP(q)
    else:
        q.append(data)

def read_udp(s):
    data,addr = s.recvfrom(1024)
    print("received message:", data)
    del q[-1]


processP(q):
    text = q.popleft()
    textReverse = text[::-1]
    print(textReverse)

def run():
    # create tcp socket
    tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        tcp.bind((host,port))
    except socket.error as err:
        print('Bind failed', err)
        return
    tcp.listen(1)
    # create udp socket
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
    udp.bind((host,port))
    print('***Socket now listening at***:', host, port)
    input = [tcp,udp]
    try:
        while True:
            inputready,outputready,exceptready = select(input,[],[])
            for s in inputready:
                if s == tcp:
                    read_tcp(s)
                elif s == udp:
                    read_udp(s)
                else:
                    print("unknown socket:", s)
    # Hit Break / Ctrl-C to exit
    except KeyboardInterrupt:
        print('\nClosing')
        raise
    tcp.close()
    udp.close()

if __name__ == '__main__':
    run()

在收到UDP消息后暫停程序,然后返回到處理階段時遇到問題。 現在,如果在處理過程中將UDP消息發送到我的程序,則直到處理結束(然后雙端隊列為空),它才會收到該消息。 我以為線程化或多處理可能會有所幫助,但我不知道如何將它們應用於代碼。

沒有人強迫您清空出隊。 您可以在使下一個工作負載出隊之前檢查UDP消息是否到達。 這是線程所能提供的,因為它們不允許您中斷任意代碼。 它們始終只能以合作方式終止。

如果單項處理花費的時間太長,則可以選擇對工作項進行多處理,因為您可能會終止外部流程。

在繼續處理下一個工作負載之前,請使用select.select在較短的超時時間內檢查套接字上的傳入數據。 或者,您可以使用線程等待線程上的輸入並處理出隊。

編輯這是使您的代碼可與python3一起使用,select.select和一個超時。 觸發read_udp可以與帶回顯echo foo | nc -4 -u localhost 5005 netcat一起使用echo foo | nc -4 -u localhost 5005 echo foo | nc -4 -u localhost 5005但隨后觸發異常,因為您假設出隊中存在元素-這是一個應用程序邏輯問題,與如何交錯偵聽和工作這一問題無關。

import socket
import select
from collections import deque

host = "localhost"
port = 5005
backlog = 5
BUFSIZE = 4096
q = deque()


def read_tcp(s):
    conn, addr = s.accept()
    print('Connected with', *addr)
    while 1:
        data = conn.recv(BUFFER_SIZE)
        if not data: break
        print("received data:", data)
        conn.send(data)  # echo
    conn.close()
    if (data == 'finish'):
        processP(q)
    else:
        q.append(data)

def read_udp(s):
    data,addr = s.recvfrom(1024)
    print("received message:", data)
    del q[-1]


def processP(q):
    text = q.popleft()
    textReverse = text[::-1]
    print(textReverse)

def run():
    # create tcp socket
    tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    try:
        tcp.bind((host,port))
    except socket.error as err:
        print('Bind failed', err)
        return
    tcp.listen(1)
    # create udp socket
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
    udp.bind((host,port))
    print('***Socket now listening at***:', host, port)
    input = [tcp,udp]
    try:
        while True:
            print("select.select")
            inputready,outputready,exceptready = select.select(input,[],[], 0.1)
            for s in inputready:
                if s == tcp:
                    read_tcp(s)
                elif s == udp:
                    read_udp(s)
                else:
                    print("unknown socket:", s)
    # Hit Break / Ctrl-C to exit
    except KeyboardInterrupt:
        print('\nClosing')
        raise
    tcp.close()
    udp.close()

if __name__ == '__main__':
    run()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM