2015-10-13 198 views
2

我試圖編寫一個Python版本的例子here,但由於某種原因,每次調用socket.recvfrom()時,我都會在客戶端和服務器端進行編程, address返回值是None。我唯一能想到的就是它可能與插座是STREAM插座的事實有關,但是當我嘗試將其類型更改爲socket.SOCK_DGRAM時,我在致電socket.listen()時遇到錯誤。我該如何解決這個問題?Python:socket.recvfrom()返回地址

def server(port): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.bind(('127.0.0.1', port)) 
    sock.listen(5) 
    clientsocket, address = sock.accept() 

    kkp = KnockKnockProtocol(); #Class which implements knock knock 
    outputLine = kkp.processInput(); 
    clientsocket.sendto(outputLine, address) 

    inputLine, address = clientsocket.recvfrom(MAX_BYTES) 

    while inputLine: 
     print inputLine, address 
     outputLine = kkp.processInput(inputLine); 
     clientsocket.sendto(outputLine, address) 
     if outputLine == "Bye.": 
      break 
     inputLine, address = clientsocket.recvfrom(MAX_BYTES) 


def client(port): 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.connect(("127.0.0.1", port)) 
    fromServer, address = sock.recvfrom(MAX_BYTES) 

    while fromServer: 
     print "Server: " + fromServer 
     if fromServer == "Bye.": 
      break 

     fromUser = raw_input() 
     if fromUser: 
      print "Client: " + fromUser 
      sock.sendto(fromUser, ("127.0.0.1", port)) 
     fromServer, address = sock.recvfrom(MAX_BYTES) 


if __name__ == '__main__': 
    choices = {'client': client, 'server': server} 
    parser = argparse.ArgumentParser(description='Send and receive UDP locally') 
    parser.add_argument('role', choices=choices, help='which role to play') 
    parser.add_argument('-p', metavar='PORT', type=int, default=1060, help='UDP port (default 1060)') 
    args = parser.parse_args() 
    function = choices[args.role] 
    function(args.p) 

回答

2

可以使用數據報套接字或流套接字。你正試圖分化差異。你想用哪個?如果您想要基於連接的字節流協議,請使用流套接字。如果你想要一個無連接的數據報協議,使用數據報套接字。

如果您想使用流套接字,請不要使用recvfrom。它基於連接,您可以接收的唯一東西是來自該特定連接的字節。

如果要使用數據報套接字,請不要使用listenaccept。既然它沒有連接,你既不能聽也不能接受連接。

+0

好吧,那麼如果我想使用流套接字,那麼如何將數據發送回另一端的套接字?同樣,如果我想使用數據報套接字,我只是直接發送到一個地址? –

+2

@SimonZhu對於流套接字,您可以使用'write'將其發送到流的另一端。對於數據報套接字,你可以使用'sendto'發送到一個特定的地址。 –