简体   繁体   English

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

[英]Python Sockets - Sending a packet to a server and waiting for a response

I am currently implementing the code below to send a packet to Parallels PVA XML API . 我目前正在实现以下代码,以将数据包发送到Parallels PVA XML API I am trying to send two XML packets to the server. 我正在尝试将两个 XML数据包发送到服务器。 The first one is a login packet that specifies the users credentials, and the second one is a packet containing information about an API request. 第一个是指定用户凭据的登录数据包,第二个是包含有关API请求信息的数据包。 These packets are supposed to be separated by a null byte \\0 . 这些数据包应该以空字节\\0分隔。 Normally, the server sends back multiple packets the first one being a clarification that the login was successful, and the second one containing information about the API request. 通常,服务器会发回多个数据包,第一个数据包是登录成功的说明,第二个数据包包含有关API请求的信息。

The problem that i'm having is that it seems like the second packet isn't being sent. 我遇到的问题是似乎第二个数据包没有被发送。 The only response that I am getting back is the first packet that clarifies that the login was successful, but i'm not getting back a packet containing information about the API request. 我得到的唯一响应是第一个说明登录成功的数据包,但我没有得到包含有关API请求信息的数据包。 I thought that this could be because i'm sending a null byte, so I tried encoding everything in base64, but I ended up at the same result. 我以为这可能是因为我要发送一个空字节,所以我尝试在base64中对所有内容进行编码,但最终得到了相同的结果。

So then it seems to me that either the connection is being closed and the server isn't getting enough time to send it's second packet, or the packet is ignored completely because of the null byte. 因此在我看来,要么连接已关闭,服务器没有足够的时间发送第二个数据包,要么由于空字节而完全忽略了该数据包。

Any help or comments will be greatly appreciated. 任何帮助或评论将不胜感激。 Thank you in advance! 先感谢您!

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)

Please not that there is no information in the packets on purpose, because it contains sensitive information, and the ip address was replaced by "[IP_ADDRESS]" on purpose 请不要故意在数据包中没有信息,因为它包含敏感信息,并且ip地址被“ [IP_ADDRESS]”故意取代了

The problem is, you tried to send too many bytes at one time, and \\0 will terminate the whole message, thus the remaining part has never been sent. 问题是,您尝试一次发送太多字节, \\0将终止整个消息,因此剩余部分从未发送过。 I've mimic a similar client/server and here is the response: 我模仿了类似的客户端/服务器,这是响应:

Server is just an echo type 服务器只是回显类型

... ...

Client, from your code with slight changes 客户端,从您的代码中进行了些微更改

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>
...

You will see, the 2packet never got sent since it's terminated by the null byte with the message body over 131072 bytes, which is longer than the second part message body. 您会看到, 2packet从未发送过,因为它被空字节终止,消息主体超过131072字节,比第二部分消息主体更长。

So to tackle this, you just need to send a single byte on each loop, so null byte will only terminate itself, and your next byte until end of message can be sent: 因此,要解决此问题,您只需要在每个循环上发送一个字节,那么空字节将仅终止自身,而下一个字节直到可以发送消息末尾为止:

revised version by sending single byte 通过发送单字节修改版本

... 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:  <
...

sock.recv can get up to 131072 bytes, but it's totally ok that it reads only 1 byte. sock.recv最多可以获取131072个字节,但是完全可以读取1个字节是完全可以的。 If you close the socket immediately, the reply gets lost. 如果立即关闭套接字,答复将丢失。 You have to repeat recv until you've read all the information the server sends. 在读取服务器发送的所有信息之前,必须重复执行recv Are all packets terminated by \\0 ? 所有数据包都以\\0结尾吗? Then read till you get the expected number of '\\0's. 然后阅读,直到获得期望的数字'\\ 0'。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM