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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26768213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:59:42  来源:igfitidea点击:

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

pythonpython-sockets

提问by Raffi

I am currently implementing the code below to send a packet to Parallels PVA XML API. I am trying to send twoXML packets to the server. 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. These packets are supposed to be separated by a null byte \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.

我目前正在实施以下代码以将数据包发送到Parallels PVA XML API。我正在尝试向服务器发送两个XML 数据包。第一个是指定用户凭据的登录数据包,第二个是包含 API 请求信息的数据包。这些数据包应该由空字节分隔\0。通常,服务器会发回多个数据包,第一个数据包表示登录成功,第二个数据包包含有关 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. 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.

我遇到的问题是似乎没有发送第二个数据包。我收到的唯一响应是第一个说明登录成功的数据包,但我没有收到包含 API 请求信息的数据包。我认为这可能是因为我发送了一个空字节,所以我尝试在 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>
import socket
from time import sleep
def client():
    # I change second packet to 2packet for visually distinguish the packets
    packet = "<packet></packet>
... 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:  <
...
<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> ...
<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]”

采纳答案by Anzel

The problem is, you tried to send too many bytes at one time, and \0will terminate the whole message, thus the remaining part has never been sent. I've mimic a similar client/server and here is the response:

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

Server is just an echo type

服务器只是一个回声类型

...

...

Client, from your code with slight changes

客户端,从您的代码略有变化

##代码##

You will see, the 2packetnever got sent since it's terminated by the null byte with the message body over 131072bytes, 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

通过发送单字节修改版本

##代码##

回答by Daniel

sock.recvcan get up to 131072 bytes, but it's totally ok that it reads only 1 byte. If you close the socket immediately, the reply gets lost. You have to repeat recvuntil you've read all the information the server sends. Are all packets terminated by \0? Then read till you get the expected number of '\0's.

sock.recv最多可以有 131072 个字节,但它只读取 1 个字节完全没问题。如果您立即关闭套接字,回复将丢失。您必须重复,recv直到您阅读了服务器发送的所有信息。所有数据包都以\0? 然后阅读直到获得预期的 '\0' 数。