连续接收和发送

2024-06-26 00:20:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个任务,我需要连接到一个服务器(没有透露服务器的详细信息),捕获回复,修改它,并将其发回以供验证。在

我已经创建了下面的代码,这是我需要的,但问题是,在第一次正确的答复后,服务器发送另一个。在

代码:

# -*- 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

当我遇到第二个问题时,我用这段代码很好地捕获了输入并按预期进行了处理,但是当我试图发送第二个回复时,我得到了错误:

^{pr2}$

如果不关闭或关闭套接字,则不会向服务器发送任何答复。在

我怎样才能告诉我的客户发送消息并等待回复插座关闭?或者,如果我需要为每个循环打开新的套接字,该如何构造循环?来自服务器的回复每次都会改变,所以如果我完全打开新的连接并请求数据,我会得到新的回复,并且这个过程会重新开始。在

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


Tags: 代码fromimport服务器dataifbuffersocket
1条回答
网友
1楼 · 发布于 2024-06-26 00:20:45

你怎么知道它没有发送任何信息?我修改了您的代码(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运行了一个“服务器”:

^{pr2}$

启动你的程序,开始输入行(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循环并再次单击{}。第二条消息已在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. 四分之一,但最后一条信息是部分的

在使用TCP套接字操作时,必须满足场景2-5的要求。你必须分析数据,确保所有的东西都在那里,如果没有,等待更多。如果有比你期望的更多,相应地处理它们。如果它们是完整的消息,请处理它们。如果最后一条消息是部分的,则处理所有其他消息并等待更多消息。在

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

希望这对你有帮助。从套接字通信的角度来看,没有附加recv的代码似乎可以正常工作—无需关闭套接字。可能是服务器端问题、协议问题或消息解析问题。在

因此,对于您的套接字,始终只有一个recv调用。即使您希望得到某种确认而不是新消息,也只有一个处理套接字数据的位置。然后在那里做一些有条件的测试,检测你收到了什么样的消息,然后决定如何处理它。在

相关问题 更多 >