我正在进行分配,我需要连接到服务器(没有披露服务器的详细信息),捕获回复,修改并发送回来进行验证。
我创建了以下代码,它可以满足我的需求,但问题是在第一次正确回复后,服务器会发送另一个代码。
代码:
# -*- 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的回复?或者,如果我需要为每个循环打开新的套接字,应该如何构造循环?服务器的回复每次都会更改,所以如果我完全打开新连接并请求数据,我会收到新回复,然后流程从头再次开始。
更新: 问题似乎是当尝试从服务器接收第二个回复时,客户端只收到第一行消息。
答案 0 :(得分:2)
你怎么知道它不发送任何东西?我稍微修改了你的代码(在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
调用。即使您期望某种确认而不是新消息,也只有一个处理套接字数据的地方。然后在那里做某种条件来检测你收到的消息是什么类型,然后决定如何处理它。