2013-10-23 100 views
1

我是新来的Python 3.3,我开始写一个使用套接字的小猜谜游戏。然而我不断收到错误​​
我看不到为什么我在currentGuess = int(currentGuess)这行中得到这个错误,因为我在代码中有一个类似的行。如果有人能帮助我,我会非常感激。这是我的服务器和客户端代码。我曾看过类似问题的其他解决方案,但我无法为我工作。Python错误ValueError:无效文字为int()与基地10''

服务器

#!/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() 
+1

在我看来,你只会发送一个猜测,所以你需要在你的客户端代码中循环。 –

回答

1

回到家乡,从s.recv()一个空字符串意味着对方叫连接上closeshutdown(或者它被中断在一些其他的方式,对方退出,或有人撕去了以太网线)。

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

要解决这个问题,您需要发送尽可能多的猜测作为对方的期望。事情是这样的:

#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() 

同时,虽然它不造成这个特殊的问题,你的代码不能可靠地工作。 Sockets are byte streams, not message streams。不能保证每个send都会与另一侧的recv匹配。 recv可能会将send的一半或两个send捆绑在一起。在某些平台上,当你使用本地主机,发送小信息,而不是发送太快时,所有事情都会发生。在其他平台上,事情大部分时间都在工作,但偶尔也不会。在别人身上,他们经常失败。

最重要的是,由于the docs解释,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') 

最后一个问题,我不会影响你,但应该修复:

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

如果您使用makefile,如上所示,您可以通过让文件对象为你编码。只是这样做:

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

然后你就可以离开了所有的decodeencode电话。

+0

谢谢这真的有助于解决我原来的问题,并感谢您的额外提示。就像我刚刚说的初学者一样,所有的学习曲线,并感谢对事物的伟大解释 – ProgrammingRookie

+0

@ProgrammingRookie:作为一个初学者没什么问题。你可能还有更多需要学习的东西,但是你也有更少的老式坏习惯可以打破。 :) – abarnert

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)正在返回一个空字符串。这只发生在连接关闭时,所以这意味着客户端已经停止向服务器发送数据。

相关问题