簡體   English   中英

python 中套接字連接的多線程

[英]Multithreading for a socket connection in python

我正在嘗試為關鍵字抓取非常繁忙的抽搐聊天,但有時套接字會停止一瞬間,但在那一瞬間,可以通過 go 發送 5 條消息。 我想在下面的代碼中實現一些多線程但沒有運氣。 似乎他們都沒有抓住關鍵字,或者都成功了。 任何幫助表示贊賞。 下面的代碼:

import os
import time
from dotenv import load_dotenv
import socket
import logging
from emoji import demojize

import threading

# loading environment variables
load_dotenv()

# variables for socket
server = "irc.chat.twitch.tv"
port = 6667
nickname = "frankied003"
token = os.getenv("TWITCH_TOKEN")
channel = "#xqcow"

# creating the socket and connecting
sock = socket.socket()
sock.connect((server, port))
sock.send(f"PASS {token}\n".encode("utf-8"))
sock.send(f"NICK {nickname}\n".encode("utf-8"))
sock.send(f"JOIN {channel}\n".encode("utf-8"))

while True:
    consoleInput = input(
        "Enter correct answer to the question (use a ',' for multiple answers):"
    )

    # if console input is stop, the code will stop ofcourse lol
    if consoleInput == "stop":
        break

    # make array of all the correct answers
    correctAnswers = consoleInput.split(",")
    correctAnswers = [answer.strip().lower() for answer in correctAnswers]

    def threadingFunction():

        correctAnswerFound = False

        # while the correct answer is not found, the chats will keep on printing
        while correctAnswerFound is not True:

            while True:
                try:
                    resp = sock.recv(2048).decode(
                        "utf-8"
                    )  # sometimes this fails, hence retry until it succeeds
                except:
                    continue
                break

            if resp.startswith("PING"):
                sock.send("PONG\n".encode("utf-8"))

            elif len(resp) > 0:
                username = resp.split(":")[1].split("!")[0]
                message = resp.split(":")[2]
                strippedMessage = " ".join(message.split())

                # once the answer is found, the chats will stop, correct answer is highlighted in green, and onto next question
                if str(strippedMessage).lower() in correctAnswers:
                    print(bcolors.OKGREEN + username + " - " + message + bcolors.ENDC)
                    correctAnswerFound = True
                else:
                    if username == nickname:
                        print(bcolors.OKCYAN + username + " - " + message + bcolors.ENDC)
                    # else:
                        # print(username + " - " + message)
    
    t1 = threading.Thread(target=threadingFunction)
    t2 = threading.Thread(target=threadingFunction)
    t3 = threading.Thread(target=threadingFunction)

    t1.start()
    time.sleep(.3)
    t2.start()
    time.sleep(.3)
    t3.start()
    time.sleep(.3)

    t1.join()
    t2.join()
    t3.join()

首先,讓 3 個線程在同一個套接字上並行讀取沒有多大意義,它只會導致混亂和競爭條件。

但主要問題是您假設單個recv將始終讀取單個消息。 但這不是 TCP 的工作方式。 TCP沒有消息的概念,只是一個字節stream。 消息是應用程序級別的概念。 單個recv可能包含單個消息、多個消息、部分消息......

所以你必須根據應用協議定義的語義來實際解析你得到的數據,即

  1. 初始化一些緩沖區
  2. 從套接字獲取一些數據並將它們添加到緩沖區 - 不要解碼數據
  3. 從緩沖區中提取所有完整消息,分別解碼和處理每條消息
  4. 將剩余的不完整消息留在緩沖區中
  5. 繼續#2

除此之外,不要在recv(..).decode(..)期間盲目丟棄錯誤。 鑒於您使用的是阻塞套接字recv通常只有在連接出現致命問題時才會失敗,在這種情況下重試將無濟於事。 問題很可能是因為您正在對不完整的消息調用decode ,這也可能意味着無效的 utf-8 編碼。 但是,由於您只是忽略了問題,因此您基本上會丟失消息。

暫無
暫無

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

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