微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法从套接字连接获取完整数据

如何解决无法从套接字连接获取完整数据

我正在尝试编写一个从服务器接收数据流的套接字客户端。 我能够获得前几个字节,但随后就中断了。

代码

import socket
import sys

readOut = 0                 # serial data
ipaddr = "192.168.1.246"    # ip address of digital thermometer socket server

#def hitsocket(ipaddr):
    #with socket.socket(socket.AF_INET,socket.soCK_STREAM) as s:
print ("Starting up")
connected = False

with socket.socket(socket.AF_INET,socket.soCK_STREAM) as s:
    try:
        s.connect((ipaddr,8080))
        amount_received = 0
        while True:
            data = s.recv(1024)
            amount_received += len(data)
            if not data:
                break
            print(amount_received,end="\n")
            while True:
                print ("Reading: ",amount_received)
                if "Fahrenheit" in amount_received:
                    cread = amount_received[22:-2]
                    newcread = float(cread)
                    print("readOut ",amount_received,"cread ",cread,"newcread ",newcread)
                    break
                print ("Restart")
    finally:
        print(sys.stderr,'closing socket')
        s.close()

输出

Starting up
19
Writing:  1
Reading:  19
<_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'> closing socket
Traceback (most recent call last):
  File "climatemnGrdebug-v3.py",line 58,in <module>
    if "Fahrenheit" in amount_received:
TypeError: argument of type 'int' is not iterable

套接字的netcat输出

kermit@whale:~/dev $ netcat 192.168.1.246 8080
mcp9809 Fahrenheit 72.0500
mcp9809 Fahrenheit 72.0500
mcp9809 Fahrenheit 72.0500
mcp9809 Fahrenheit 72.1625
mcp9809 Fahrenheit 72.0500
mcp9809 Fahrenheit 72.0500
mcp9809 Fahrenheit 72.1625
mcp9809 Fahrenheit 72.0500

如何让我的套接输出一整行数据?

我已经阅读了 python 文档,也查看了其他示例,但我还是弄错了。

解决方法

您在 amount_received 中查找单词“Fahrenheit”,它是数据的整数计数,而不是数据本身。接收到的数据在 data 中,它是一个 Bytes 字符串。 recv 不知道服务器发送的行,它只是抓取一些字节。但是您可以缓冲接收数据并自己找到换行符。假设数据是字节编码的(ascii,Windows 代码页,utf-8 - 但不是 utf-16),你可以搜索 b'\n' 的字节,一旦你知道你有一行,将其转换为字符串进一步处理。在此示例中,我编写了一个类,该类读取字节流并在找到时返回行。

客户端.py

import socket
import sys

readOut = 0                 # serial data
#ipaddr = "192.168.1.246"    # ip address of digital thermometer socket server
# todo: change as needed for test server or real server
ipaddr = 'localhost'
ipport = 8080

#def hitsocket(ipaddr):
    #with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
print ("Starting up")
connected = False

class LineReader:

    def __init__(self,socket,encoding='ascii'):
        self.s = socket
        self.encoding = encoding
        self.buf = b''
        self.closed = False

    def readline(self):
        while True:
            index = self.buf.find(b'\n')
            if index >= 0:
                line = self.buf[:index+1]
                self.buf = self.buf[index+1:]
                return line.decode(self.encoding)
            if self.closed:
                line = self.buf
                self.buf = b''
                return line.decode(self.encoding)
            data = self.s.recv(1024)
            self.closed = len(data) == 0
            print("raw recv:",data)
            self.buf += data

with socket.socket(socket.AF_INET,socket.SOCK_STREAM) as s:
    try:
        s.connect((ipaddr,ipport))
        reader = LineReader(s)
        while True:
            line = reader.readline()
            if not line:
                break
            print(f"Reading: {line}",end='')
            if "Fahrenheit" in line:
                cread = line[22:-2]
                newcread = float(cread)
                print("cread ",cread,"newcread ",newcread)
    finally:
        print('closing socket',file=sys.stderr)
        s.close()

testserver.py

import socket
import time

test_data =  b'mcp9809 Fahrenheit 72.0500\n'
s = socket.socket()
# todo: change as needed,but must match address in client script
s.bind(('localhost',8080))
s.listen()
while True:
    c,addr = s.accept()
    # send in framents to test reassembler
    c.send(test_data)
    time.sleep(.1)
    c.send(test_data * 2)
    time.sleep(.1)
    c.send(test_data[:9])
    time.sleep(.1)
    c.send(test_data[9:])
    c.send(test_data * 3 + test_data[:9])
    time.sleep(.1)
    c.send(test_data[9:])
    c.shutdown(socket.SHUT_RDWR)
    c.close()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。