2014-11-05 84 views
1

我目前正在實施下面的代碼發送數據包到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

回答

3

問題是,您試圖一次發送太多字節,並且\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

0

sock.recv能站起來到131072字節,但它只讀取1個字節是完全可以的。如果您立即關閉套接字,則回覆會丟失。在閱讀服務器發送的所有信息之前,您必須重複recv。所有數據包是否由\0終止?然後閱讀,直到你得到預期的'\ 0's數量。

+0

是的數據包以'\ 0'結尾。我試着用你建議的方法調試我的代碼,在我的控制檯中鍵入'python',而不是關閉套接字,我等待它超時。我只是使用'sock.recv(131072)'並等待它在10秒後超時,但它仍然吐出一個數據包,然後是'\ x00'。這使我相信第二個數據包甚至沒有被服務器使用。 – Raffi 2014-11-05 23:04:46