2012-12-09 44 views
3

为了理解网络编程如何更好地完成,我一直在使用Python套接字。现在我试图建立一个连接到服务器的客户端,并可以在关闭之前发送任意数量的消息。我仍然不是很了解所有事情,我只能让它发送一条消息。对于使用套接字编程的人来说,这可能是显而易见的。有人可以向我解释如何让它发送多条消息吗?也许给我提供一个很好的资源,解释连接,绑定,关闭,recv和所有主要套接字函数的工作方式? (大部分的来源我找到刚才告诉我什么时候使用它们。)Python套接字 - 服务器只接收一次?

客户

# !usr/bin/python 

import socket 
import sys 


def main(): 
    host = "" 
    port = 8934 
    message = "Hello World!" 

    host = raw_input("Enter IP: ") 
    #Create Socket 
    try: 
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    except socket.error, msg: 
     print "Failed to create socket. Error code: %s Error Message: %s"%(str(msg[0]),msg[1]) 
     sys.exit() 
    print "Socket created" 

    #Connect to server 
    s.connect((host,port)) 

    while message != "/e": 
     #Send Data 
     message = raw_input("Send >> ") 
     try: 
      s.sendall(message) 
     except socket.error, msg: 
      print "ERROR %s"%(msg[1]) 
      print "Failed to send." 
     s.close() 

if __name__ == "__main__": 
    main() 

服务器

# !usr/bin/python 

import socket 
import sys 

HOST = "" 
PORT = 8934 
s = socket.socket() 

class BoServer: 


    def __init__(self): 
     try: 
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     except socket.error,msg: 
      print "Unable to create socket" 
      sys.exit() 
     print "Socket created." 
    def bind(self): 
     s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 
     try: 
      s.bind((HOST,PORT)) 
     except socket.error,msg: 
      print "Bind failed. Closing..." 
      sys.exit() 
     print "Socket bound." 
    def run(self): 
     while True: 
      s.listen(10) 
      print "Socket Listening" 
      conn, addr = s.accept() 
      print "Connected to %s:%s"%(addr[0],addr[1]) 
      income = conn.recv(4096) 
      if income != "": 
       print income 

def main(): 
    serv = BoServer() 
    serv.bind() 
    serv.run() 

if __name__ == "__main__": 
    main() 
+2

你只应该'listen'和'accept'一次,然后只循环'conn.recv'。 – jozzas

+0

接受()之后,您只能从新套接字读取一次套接字,然后服务器关闭套接字。 –

+0

有一点需要记住:即使在解决这个问题之后,你也不能依靠每个'recv'来获得一个'send'的结果。在本地进行测试时,它似乎可以工作99.999%的时间,但只要部署到互联网上,它就会一直失败。你可能会得到一半的“发送”或2-1/2的“发送”。如果您需要单独的消息,则需要使用分隔符(例如换行符),长度/类型/任何前缀(例如netstrings)或某些自定义消息类型(例如JSON-RPC),并且您需要'recv '放入一个缓冲区并解析它。 – abarnert

回答

6

在您的客户端,您要关闭插座在你的while True:循环中,所以你将不能在循环的未来迭代中传输更多的消息。如果您打算在不同的连接上发送每条消息,则需要在循环中创建套接字。如果你打算在同一个连接上发送多个消息,那么你需要将闭环呼叫转移到循环外部。

在服务器端,您每循环一次循环就会运行listen()一次,这是不必要的:它的目的是为缓冲传入连接设置队列长度,因此只需要调用一次。在继续进行循环的第二次迭代之前,您只接受来自套接字的单个读取,并接受另一个传入连接。

根据您希望服务器的行为方式,另一个潜在的问题是您一次只能服务一个传入连接。如果你打算处理长时间运行的连接,那么这可能是一个问题。要一次处理多个连接,您可能需要在自己的线程上处理每个连接(例如,使用SocketServer standard library moduleThreadingTCPServer类),或使用异步IO框架(如Twisted)。

+0

谢谢詹姆斯,帮我理解了一点。 – cgasser