2

我是 Python 3.3 的新手,我开始使用套接字编写一个小猜谜游戏。但是,我不断收到错误消息ValueError: invalid literal for int() with base 10: ''
,我不明白为什么会在该行中出现此错误,currentGuess = int(currentGuess)因为我的代码前面有类似的行。如果有人可以帮助我,我将不胜感激。这是我的服务器和客户端代码。我已经查看了具有类似问题的其他解决方案,但我无法为我工作。

服务器

    #!/usr/bin/python
    import random
    import sys
    import math
    import  socket

    l = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    l.bind(("127.0.0.1", 4007))
    l.listen(5)
    print("Waiting...")
    while True:
          (s,  ca) = l.accept()
          print("Connection  from",  ca)

          #Name
          s.send("What is your name?". encode())
          names = s.recv(1024).decode()
          #Guesses

          s.send("How many guesses would you like?".encode())
          guesses = s.recv(1024).decode()
          guesses = int(guesses)
          #Random Number

          correctNumber = random.randrange(0,10)
          print(correctNumber)

          #Make Guesses
          count = 0
          while count < guesses:
                s.send("Take a Guess".encode())
                currentGuess = s.recv(1024).decode()
                currentGuess = int(currentGuess)
                if currentGuess == correctNumber:
                   s.send("You WIN".encode())
                if currentGuess != correctNumber:
                   s.send("Incorrect, Try Again ".encode())
                   count = count + 1

    s.close()

客户

    #!/usr/bin/python
    import random
    import sys
    import math
    import socket

    s = socket.socket(socket.AF_INET,   
    socket.SOCK_STREAM)
    s.connect(("127.0.0.1", 4007))
    print("Wlcome to the numer guessing game")

    #Name
    print(s.recv(1024).decode())
    name = sys.stdin.readline()
    s.send(name.encode())

    #guesses
    print(s.recv(1024).decode())
    guesses = sys.stdin.readline()
    s.send(guesses.encode())

    #Make Guesses
    print(s.recv(1024).decode())
    currentGuess = sys.stdin.readline()
    s.send(currentGuess.encode())
    print(s.recv(80).decode())
    s.close()
4

2 回答 2

1

当您尝试调用int空字符串时会出现该错误:

>>> int("")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''

这意味着当你这样做时:

currentGuess = s.recv(1024).decode()
currentGuess = int(currentGuess)

currentGuess正在设置为''。也就是说,s.recv(1024)返回一个空字符串。这仅在连接关闭时发生,因此这意味着客户端已停止向服务器发送数据。

于 2013-10-23T20:32:41.137 回答
1

取回一个空字符串s.recv()意味着对方呼叫closeshutdown连接上(或者它以某种其他方式被中断 - 对方退出,或者有人扯掉了以太网线)。

看看你的服务器代码,如果你说你想要 3 次猜测,它会尝试recv3 次......但客户端只会尝试send一次,之后它会close连接。这意味着recv服务器上的 next 将返回一个空字符串,这正是您所看到的。

要解决此问题,您需要发送与对方期望一样多的猜测。像这样的东西:

#Make Guesses
for i in range(int(guesses)):
    print(s.recv(1024).decode())
    currentGuess = sys.stdin.readline()
    s.send(currentGuess.encode())
    print(s.recv(80).decode())
s.close()

同时,虽然它没有引起这个特殊问题,但您的代码不能可靠地工作。套接字是字节流,而不是消息流。不能保证每个send都会与recv另一侧的 a 匹配。recv可能会得到一半的 a或send两个sends 捆绑在一起。在某些平台上,当您使用 localhost 并发送小消息,而不是发送太快时,一切都会发生。在其他平台上,大部分时间都可以正常工作,但偶尔不会。在其他人身上,他们经常失败。

最重要的是,正如文档所解释的那样,send永远不能保证发送其整个字符串;这就是为什么它返回实际发送的字节数。您可以通过使用来解决这个问题sendall,但这对解决其他问题没有帮助。

您必须通过设计和实现协议,在 TCP 字节流之上构建消息流。这听起来很吓人,但是一个非常简单的协议,“所有消息都以换行符结尾”,只需使用该makefile方法就可以实现,如下所示:

s.connect(("127.0.0.1", 4007))
f = s.makefile('r+b')

现在,每次您执行以下任一操作时:

foo = s.recv(80)
s.send(bar)

......而不是做这些:

foo = f.readline().strip()
f.write(bar + '\n')

最后一个不影响您但应该解决的问题:

encode在没有参数的情况下调用decode几乎总是一个坏主意,尤其是对于网络字节。你要求 Python 用sys.getdefaultencoding(). 您能确定客户端和服务器上的默认编码是相同的吗?你能确定它可以处理用户可能键入的任何内容吗?在典型的 Windows 机器上,它可能类似于'cp1252',这意味着如果用户键入一个汉字,客户端将退出一个UnicodeError,这对用户不是很友好。正确的做法是明确使用'utf-8'. (这意味着您的协议现在是“所有消息都采用 UTF-8 格式,并以换行符结尾。”)

如果您makefile按照上面的建议使用,您可以通过让文件对象为您进行编码来更轻松地解决这个问题。只需这样做:

f = s.makefile('r+', encoding='utf-8')

然后你可以省去所有的decodeencode电话。

于 2013-10-23T20:33:12.123 回答