Python客户机有时从不接收数据

2024-10-05 14:30:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个小的客户端/服务器游戏。虽然它似乎大部分工作,服务器和客户端之间的通信似乎有点不正常,我不太清楚是什么原因造成的。你知道吗

因此,我启动server.py,然后启动client.py,客户机连接并接收第一条消息的长度,它接收实际消息并完美地显示它。但是当它再次运行时,它永远不会得到第二条消息,只知道它有多长。它只是无限期地等待(好吧,我猜是TCPs超时时间)。你知道吗

我知道有些字节可能会丢失,但是如果仍然有连接的话,TCP是用来保证传输的,对吗?UDP就是抛出数据包的那个?似乎也没有断开。这也是整个localhost,所以它甚至没有离开我的机器。你知道吗

为了避免时间问题,我在等待客户机用户输入的回复之前,还对服务器进行了time.sleep(.5)。你知道吗

为什么客户机收到第一条消息而不是第二条消息,尽管使用相同的方法发送它?你知道吗

服务器.py

import socket, random, pickle, os.path, csv, time

# Global variables
c = 0
a = ""

def SendIt(d):
    global c
    d = pickle.dumps(d)
    MSGLEN = len(d)
    print ("MSGLEN =", MSGLEN) # REMOVE AFTER DEBUG
    MSGLENstr = pickle.dumps(MSGLEN)
    c.send(MSGLENstr)
    totalsent = 0
    while totalsent < MSGLEN:
        sent = c.send(d[totalsent:])
        if sent == 0:
            raise RuntimeError("socket connection broken")
        totalsent = totalsent + sent

def TheMainGame():
    def within(val, goal):
        i = abs(val - goal)
        if (i <= 3):
            return True
        else:
            return False

    def try_int(k):
        try:
            return int(k)
        except ValueError:
            return k

    def GetScoreboard():
        with open('Scores.csv', 'r') as scores:
            reader = csv.reader(scores)
            tscores = [[str(e) for e in r] for r in reader if len(r) > 0]
            return tscores

    def WriteScore(gscore):
        global c, a, tscore
        exists = os.path.isfile("Scores.csv")
        if (exists == False): # Checks if file exists, if not create it
            nscore = [[gscore, a[0]]] # Add first line of data
            with open("Scores.csv", "a") as scores:
                writer = csv.writer(scores)
                [writer.writerow(r) for r in nscore]
        else: # File exists so we add to it
            nscore = [[gscore, a[0]]]
            with open('Scores.csv', 'r') as scores:
                reader = csv.reader(scores)
                tscores = [[str(e) for e in r] for r in reader if len(r) > 0]
            tscores = [[try_int(l) for l in i] for i in tscores]
            tscores.append(nscore[0])
            tscores = [x for x in tscores if x != []]
            tscores.sort(key=lambda x: x[0])
            if (len(tscores) > 5):
                tscores = tscores[:5]
                with open("Scores.csv", "w+") as scores:
                    writer = csv.writer(scores)
                    [writer.writerow(r) for r in tscores]
            elif (len(tscores) <= 5):
                with open("Scores.csv", "w+") as scores:
                    writer = csv.writer(scores)
                    [writer.writerow(r) for r in tscores]

    def Guess():
        global c
        guesses = 0
        while True:
            data = ["open", "What is your guess?"]
            SendIt(data)
            time.sleep(.5)
            print("sent question") # REMOVE AFTER DEBUG
            t = int(c.recv(1000).decode())
            print("waiting for reply") # REMOVE AFTER DEBUG
            if (t == x):
                guesses += 1
                data = ["msg","Correct!"]
                SendIt(data)
                if (guesses == 1):
                    msg = "You took ", guesses, " guess!"
                else:
                    msg = "You took ", guesses, " guesses!"
                msg = [str(x) for x in msg]
                msg = ",".join(msg)
                msg = msg.replace(",", "")
                data = ["msg", msg]
                SendIt(data)
                WriteScore(guesses)
                data = ["msg", "Heres the leaderboard:"]
                SendIt(data)
                data = ["scores", GetScoreboard()]
                SendIt(data)
                data = ["closing", "Thanks for playing!"]
                SendIt(data)
                c.close()
                break
            elif (within(t,x) == True):
                guesses += 1
                data = ["incorrect", "Close!"]
                SendIt(data)
            elif (within(t,x) == False):
                guesses += 1
                data = ["incorrect", "Far"]
                SendIt(data)
            else:
                data = ["closing", "There was an error computing the value"]
                SendIt(data)
                c.close()
                break

    x = random.randrange(1, 20, 1)
    print(x) # REMOVE AFTER DEBUG
    Guess()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 4001))
s.listen(5)
while True:
    (c,a) = s.accept()
    data = ["msg", "Hello user!"]
    SendIt(data)
    TheMainGame()

客户端.py

import socket, pickle

# Global variables
connected = False
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
data = ["closing", "Connection closed"]

def GetData():
    global s, data
    chunks = []
    bytes_recd = 0
    MSGLEN = s.recv(512) # OLD RECV
    MSGLEN = pickle.loads(MSGLEN)
    print ("MSGLEN =", MSGLEN) # REMOVE AFTER DEBUG
    while bytes_recd < MSGLEN:
        chunk = s.recv(min(MSGLEN - bytes_recd, 2048))
        print("chunk =", chunk) # REMOVE AFTER DEBUG
        if chunk == b'':
            raise RuntimeError("socket connection broken")
        chunks.append(chunk)
        bytes_recd = bytes_recd + len(chunk)
    data =  b''.join(chunks)
    data = pickle.loads(data)
    print("data after depickled=", data) # REMOVE AFTER DEBUG

def SendData():
    global s
    sdata = input()
    s.send(sdata.encode())


def Connect():
    global s, connected
    s.connect(("127.0.0.1", 4001))
    connected = True

# Connect to server
Connect()

# Send/recive data till session ends
while (connected == True):
    print("fetching data") # REMOVE AFTER DEBUG
    GetData()
    print ("got data") # REMOVE AFTER DEBUG
    if (data[0] == "closing"):
        print (data[1])
        s.close()
        connected = False
        break
    elif (data[0] == "incorrect"):
        print (data[1])
    elif (data[0] == "open"):
        print("open task running") # REMOVE AFTER DEBUG
        print (data[1])
        print("printed data[1]") # REMOVE AFTER DEBUG
        SendData()
    elif (data[0] == "msg"):
        print (data[1])
    elif (data[0] == "scores"):
        data = data[1]
        data = [",".join(i) for i in data]
        data = [i.replace(",", " - ") for i in data]
        print("Guesses - User")
        print(*data, sep='\n')
    else:
        print ("An error occured!")


服务器输出

MSGLEN = 36
5
MSGLEN = 45
sent question

客户端输出

fetching data
MSGLEN = 36
chunk = b'\x80\x03]q\x00(X\x03\x00\x00\x00msgq\x01X\x0b\x00\x00\x00Hello user!q\x02e.'
data after depickled= ['msg', 'Hello user!']
got data
Hello user!
fetching data
MSGLEN = 45


服务器完成后不会有任何输出,我只是把它放进去帮我调试。客户机中的大多数输出也不存在,同样,它只是用于调试。我已经用# REMOVE AFTER DEBUG标记了所有调试行,以便于查找。如您所见chunk = s.recv(min(MSGLEN - bytes_recd, 2048))永远不会完成第二次。你知道吗


Tags: csvindebugfordataifmsgsocket
1条回答
网友
1楼 · 发布于 2024-10-05 14:30:23

这是我自己解决的基于逻辑的错误。你知道吗

我删除了服务器中的time.sleep(.5)行,并将其上移到SendIt(),将其更改为time.sleep(.1),使服务器在将数据发送到客户端之前休眠0.1秒。要从以下角度看问题:

def Guess():
    global c
    guesses = 0
    while True:
        data = ["open", "What is your guess?"]
        SendIt(data)
        """time.sleep(.5)""" # This line gets removed 
        print("sent question")
        t = int(c.recv(1000).decode())
        print("waiting for reply")

以及

def SendIt(d):
    global c
    d = pickle.dumps(d)
    MSGLEN = len(d)
    print ("MSGLEN =", MSGLEN)
    MSGLENstr = pickle.dumps(MSGLEN)
    time.sleep(.1) # This new line makes it pause 0.1 seconds before sending the data
    c.send(MSGLENstr)
    totalsent = 0
    while totalsent < MSGLEN:
        sent = c.send(d[totalsent:])
        if sent == 0:
            raise RuntimeError("socket connection broken")
        totalsent = totalsent + sent

希望这能帮助别人!还要记住import time。你知道吗

相关问题 更多 >