[英]Continous receiving & sending on a socket
我正在分配需要連接到服務器(未披露服務器的詳細信息),捕獲答復,對其進行修改並將其發回以供驗證的工作。
我創建了下面的代碼來滿足我的需要,但是問題是在第一個正確答復之后,服務器發送了另一個。
碼:
# -*- encoding: utf-8 -*-
import socket
from decryptmsg import decryptmsg
from cleanmsg import cleanmsg
#connection
ip="<IP>"
port=4000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip,port))
def recvall(sock):
BUFFER = 8192
data = b''
while True:
part = sock.recv(BUFFER)
data += part
if len(part) < BUFFER:
break
return data
while True:
print "[+] start communication"
data = recvall(sock)
print data
data = cleanmsg(data)
if data != None:
valmis = decryptmsg(str(data))
if valmis == None:
print "[-] no results"
break
else:
print "[+] sending message... "
sock.send(valmis)
continue
當我遇到第二個問題時,使用此代碼可以很好地捕獲輸入並按預期進行處理,但是當我嘗試將第二個回復發送回時,出現錯誤:
Traceback (most recent call last):
File "challenge.py", line 28, in <module>
sock.send(valmis)
socket.error: [Errno 32] Broken pipe
如果我不關閉或關閉套接字,則不會發送任何答復到服務器。
我如何告訴我的客戶發送消息並等待不帶socket.shutdown的答復? 或者,如果我需要為每個循環打開新的套接字,應該如何構造循環? 服務器的回復每次都會更改,因此,如果我完全打開新連接並請求數據,則會收到新的回復,並且該過程將從頭開始。
更新:問題似乎是在嘗試從服務器接收第二個答復時,客戶端僅接收到第一行消息。
您怎么知道它什么都不發送? 我對您的代碼進行了一些修改(else:子句有些奇怪,稍后再講)。
import socket
#connection
ip="localhost"
port=4000
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((ip,port))
while True:
data = sock.recv(8192)
if not data: break;
print data
if data != None:
valmis = data
if valmis == None:
print "[-] no results"
break
else:
print "[+] sending message... "
sock.send(valmis) #this never gets sent without
continue
基本上,這是代碼的剝離版本-無需解密或外部功能。 它只是發回從服務器收到的任何內容。
然后我用ncat運行了一個“服務器”:
ncat -l 4000
啟動程序並開始輸入行(1、2、3、4等),這發生在“服務器”上。 客戶端立即回顯我的消息:
test@xyzzy:/tmp$ ncat -l 4000
1
1
2
2
3
3
而這發生在客戶端:
test@xyzzy:/tmp$ python so.py
1
[+] sending message...
2
[+] sending message...
3
[+] sending message...
對我來說,這段代碼看起來不錯。 如果服務器未收到您的答復,則可能是服務器端存在問題。 例如,可能期望響應中有終止符。 您的cleanmsg
是否清除消息過多,例如刪除尾隨的換行符,並且服務器希望接收到該消息?
您原來的else子句中有一個問題,因為您在那里執行了另一個sock.recv()
。 這意味着在收到回復后,您將阻止在那里等待來自服務器的下一條消息,並且當收到一條消息時,您將continue
循環並再次點擊sock.recv()
。 第二條消息已在您的else子句中使用。
如果您的服務器以某種方式確認您的解密,則這可能是有意的。 如果您的協議是這樣的:
server -> client (request)
client -> server (decrypted message)
server -> client (some kind of acknowledgement - unclear from your code)
server -> client (request 2)
etc.
那么您可能已經在Jason的評論中找到了問題。 TCP套接字與消息的概念完全無關。 他們只是傳輸數據。 當您的代碼sock.recv()
,可能發生以下五種情況之一:
始終在使用TCP套接字進行操作時,必須滿足方案2-5。 您必須解析數據,確保所有內容都在其中,否則請等待更多。 如果超出您的預期,請相應地處理它們。 如果它們是完整的消息,請對其進行處理。 如果最后一條消息不完整,請處理其他所有內容,然后再等待更多。
如果消息似乎在使用TCP套接字的自制通信協議中“消失”,則99%的問題是由假設套接字知道或關心“消息”的結構是引起的。 一個非常常見的錯誤是將套接字讀為空並忽略在收到第一條消息后收到的所有內容。
希望這會有所幫助。 從套接字通信的角度來看,沒有附加recv的代碼似乎可以正常工作-無需關閉套接字。 它可能是服務器端問題,協議問題或消息解析問題。
因此,套接字始終只有一個recv
調用。 即使您期望某種形式的確認而不是一條新消息,也只能在一個地方處理套接字數據。 然后在該處執行某種有條件的操作,以檢測您收到的消息種類,然后決定如何處理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.