Python套接字 - 发送数据包到服务器并等待响应

问题描述:

我目前正在实施下面的代码发送数据包到Parallels PVA XML API。我正尝试向服务器发送两个 XML数据包。第一个是指定用户凭证的登录数据包,第二个是包含有关API请求信息的数据包。这些数据包应该被空字节\0分开。通常,服务器发回多个数据包,第一个是澄清登录成功,第二个包含有关API请求的信息。Python套接字 - 发送数据包到服务器并等待响应

我遇到的问题是,它似乎没有发送第二个数据包。我回来的唯一答案是第一个明确说明登录成功的数据包,但我没有找回包含有关API请求信息的数据包。我认为这可能是因为我发送了一个空字节,所以我尝试在base64中对所有内容进行编码,但我最终获得了相同的结果。

那么在我看来,连接正在关闭,服务器没有足够的时间发送第二个数据包,或者数据包由于空字节而被完全忽略。

任何帮助或意见将不胜感激。先谢谢你!

import socket 
import base64 

def client(string): 
    HOST, PORT = '[IP_ADDRESS]', 4433 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.settimeout(10) 
    sock.connect((HOST, PORT)) 
    sock.send(base64.b64encode(string)) 
    reply = sock.recv(131072) 
    sock.close() 

    return reply 

packet = "<packet></packet>\0<packet></packet>" 
print client(packet) 

请也不是说在故意包没有任何信息,因为它包含敏感信息,IP地址是由“[IP地址]”取代故意

+0

什么是服务器协议? – Anzel 2014-11-05 22:42:03

+0

@Anzel ** TCP ** - 客户端/服务器协议 – Raffi 2014-11-05 22:49:37

+0

空字节跳过您的整个** 131072 **字节发送,因此第二部分永远不会到达。提供的答复 – Anzel 2014-11-05 23:39:38

问题是,您试图一次发送太多字节,并且\0将终止整个消息,因此其余部分从未发送过。 我已经模拟了类似的客户端/服务器和这里的响应:

服务器仅仅是一个回声型

...

客户端,从您的代码略有改动

import socket 
from time import sleep 
def client(): 
    # I change second packet to 2packet for visually distinguish the packets 
    packet = "<packet></packet>\0<2packet></2packet>" 
    HOST, PORT = '127.0.0.1', 4433 
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
    sock.settimeout(10) 
    sock.connect((HOST, PORT)) 
    while True: 
     try: 
      sock.send(packet) 
      sleep(1) 
      # this is the problem here 
      reply = sock.recv(131072) 
      if not reply: 
       break 
      print "recvd: ", reply 
     except KeyboardInterrupt: 
      print "bye" 
      break 
    sock.close() 
    return 

client() 
recvd: WelcomeOK...<packet></packet> # the null byte teminate the send and skip all remaining message 
recvd: OK...<packet></packet> 
recvd: OK...<packet></packet> 
recvd: OK...<packet></packet> 
... 

你会看到,2packet从未被发送,因为它由空字节终止,消息正文超过字节,这是l比第二部分消息正文更加重要。通过发送单

修订版:

因此,要解决这个问题,你只需要在每次循环发送一个字节,所以空字节只会自行终止,而你的下一个字节,直到消息末尾可以发送字节

... previous code 
    while True: 
     try: 
      sock.send(packet) 
      sleep(1) 
      reply = sock.recv(1) 
      if not reply: 
       break 
      print "recvd: ", reply 
     except KeyboardInterrupt: 
      print "bye" 
      break 
    sock.close() 
    return 

client() 
recvd: W 
recvd: e 
recvd: l 
recvd: c 
recvd: o 
recvd: m 
recvd: e 
recvd: O 
recvd: K 
recvd: . 
recvd: . 
recvd: . 
recvd: < 
recvd: p 
recvd: a 
recvd: c 
recvd: k 
recvd: e 
recvd: t 
recvd: > 
recvd: < 
recvd:/
recvd: p 
recvd: a 
recvd: c 
recvd: k 
recvd: e 
recvd: t 
recvd: > 
recvd:  # <== this null byte terminates single byte send 
recvd: < # <== and next loop it tries to send the next byte, goal achieved 
recvd: 2 
recvd: p 
recvd: a 
recvd: c 
recvd: k 
recvd: e 
recvd: t 
recvd: > 
recvd: < 
... 
+1

@Raffi,很高兴它有帮助,空字节有时是一种邪恶:) – Anzel 2014-11-05 23:55:06

sock.recv能站起来到131072字节,但它只读取1个字节是完全可以的。如果您立即关闭套接字,则回复会丢失。在阅读服务器发送的所有信息之前,您必须重复recv。所有数据包是否由\0终止?然后阅读,直到你得到预期的'\ 0's数量。

+0

是的数据包以'\ 0'结尾。我试着用你建议的方法调试我的代码,在我的控制台中键入'python',而不是关闭套接字,我等待它超时。我只是使用'sock.recv(131072)'并等待它在10秒后超时,但它仍然吐出一个数据包,然后是'\ x00'。这使我相信第二个数据包甚至没有被服务器使用。 – Raffi 2014-11-05 23:04:46