持续接收&发送套接字

时间:2018-03-21 13:40:32

标签: python sockets

我正在进行分配,我需要连接到服务器(没有披露服务器的详细信息),捕获回复,修改并发送回来进行验证。

我创建了以下代码,它可以满足我的需求,但问题是在第一次正确回复后,服务器会发送另一个代码。

代码:

# -*- 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的回复?或者,如果我需要为每个循环打开新的套接字,应该如何构造循环?服务器的回复每次都会更改,所以如果我完全打开新连接并请求数据,我会收到新回复,然后流程从头再次开始。

更新: 问题似乎是当尝试从服务器接收第二个回复时,客户端只收到第一行消息。

1 个答案:

答案 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()时,可能会发生以下五种情况之一:

  1. 套接字和调用块中没有任何内容
  2. 有一个完整的“消息”,只有插槽中的消息才能收到
  3. 有部分消息,您将收到该消息。要么是因为消息超过了8192个字节,要么当服务器只传输了一些消息数据时,你的代码就决定读取。
  4. 有两个或更多完整的“消息”在等待,您将全部收到。
  5. 四个,但最后一条消息是部分
  6. 使用TCP套接字时,始终必须满足方案2-5。您必须解析数据,确保一切都在那里,如果没有,请等待更多。如果超出预期,则相应地处理它们。如果它们是完整的消息,请处理它们。如果最后一条消息是部分的,则处理其他所有消息并等待更多消息。

    如果消息似乎在使用TCP套接字的自制通信协议中“消失”,则99%的问题是由于假设套接字知道或关心“消息”的结构而引起的。一个非常常见的错误是将您的套接字读为空并忽略您在收到第一条消息后收到的所有内容。

    希望这有帮助。没有额外的recv的代码似乎从套接字通信的角度来看很好 - 不需要关闭套接字。它可能是服务器端问题,协议问题或消息解析问题。

    出于这个原因,您的套接字始终只有一个recv调用。即使您期望某种确认而不是新消息,也只有一个处理套接字数据的地方。然后在那里做某种条件来检测你收到的消息是什么类型,然后决定如何处理它。