问题描述
我正在尝试编写一个从服务器接收数据流的套接字客户端。 我能够获得前几个字节,但随后就中断了。
代码:
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
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()