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

Raffi picture Raffi · Nov 5, 2014 · Viewed 25.9k times · Source

I am currently implementing the code below to send a packet to Parallels PVA XML API. I am trying to send two XML 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.

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.

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

Answer

Anzel picture Anzel · Nov 6, 2014

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

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