Python - send uint8 and uint16 to socket - python

I'm trying to send some data with a python script to a java server. I use the socket module in python to send and recieve data.
When I send data, I need to specify a header with the datalength in it. The header is as following:
a uint8 for the version number
a uint8 for padding ('reserved')
a uint16 for the length of the data that is sent
That is a total of 32 bits.
I can use numpy to create an array with a certain data type, but the problem is sending this data through the socket. I use the following function to send data:
def send(socket, message):
r = b''
totalsent = 0
# as long as not everything has been sent ...
while totalsent < len(message):
# send it ; sent = actual sent data
sent = socket.send(message[totalsent:])
r += message[totalsent:]
# nothing sent? -> something wrong
if sent == 0:
raise RuntimeError("socket connection broken")
# update total sent
totalsent = totalsent + sent
return r
message = (something_with_numpy(VERSION_NUMBER, PADDING, len(data)))
send(socket, message)
I keep getting TypeErrors with this function. These pop up at len(message), r += message[...], or some other place.
I was wondering if there is a better way to do this, or how to fix this so it does work?
UPDATE: here are some exact error traces. I have tried several different things, so these error traces might have become irrelevant.
Traceback (most recent call last):
File "quick.py", line 47, in <module>
header += numpy.uint8(VERSION_NUMBER)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')
header = numpy.array([VERSION_NUMBER * 255 + PADDING, len(greetData)], dtype=numpy.uint16)
Traceback (most recent call last):
File "quick.py", line 48, in <module>
print(header + greetData)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S22') dtype('S22') dtype('S22')
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.uint8(VERSION_NUMBER))
File "quick.py", line 13, in send
while totalsent < len(message):
TypeError: object of type 'numpy.uint8' has no len()
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.array([VERSION_NUMBER], dtype=numpy.uint8))
File "quick.py", line 17, in send
r += message[totalsent:]
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')

You'll want to use the struct module to format the header before sending the data.
import struct
def send_message(socket, message):
length = len(message)
version = 0 # TODO: Is this correct?
reserved = 0 # TODO: Is this correct?
header = struct.pack('!BBH', version, reserved, length)
message = header + message # So we can use the same loop w/ error checking
while ...:
socket.send(...)

Related

TypeError: must be str, not NoneType in bluetooth

`
def arduino_connect():
global sock
print("Cihazlar axtarılır....")
nearby_devices = bluetooth.discover_devices()
num = 0
for i in nearby_devices:
num+=1
print(str(num)+":"+bluetooth.lookup_name(i)+" MAC: "+i)
if i=="00:21:13:00:EF:19":
selection = num-1
bd_addr = nearby_devices[selection]
port = 1
print("Sən seçdin:" +bluetooth.lookup_name(bd_addr))
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((bd_addr,port))
`
Traceback (most recent call last):
File "ordubot.py", line 92, in <module>
test(wake)
File "ordubot.py", line 81, in test
response(voice)
File "ordubot.py", line 57, in response
arduino_connect()
File "ordubot.py", line 38, in arduino_connect
print(str(num)+":"+bluetooth.lookup_name(i)+" MAC: "+i)
TypeError: must be str, not NoneType
This code gives this error, can you please help?
In this code, I want python to connect to the mac address specified by bluetooth, but this code gives an error.
When joining items using the + operator, they have to be of the same type.
That means that if bluetooth.lookup_name(i) returns a result which isn't a string (a NoneType in your case) than the concatenation fails.
You can use format string to print the result anyway -
print(f"{}:{} MAC: {}".format(num, bluetooth.lookup_name(i), i)
This will work even if not all of the arguments of format are strings.

Porting Python2 to Python3 - Reading Bytes from a socket and using unpack() correctly

There is code here that I am trying to convert from Python2 to Python3. In this section of code, data is received from a socket. data is declared to be an empty string and then concatenated. This is an important Python2 to 3 distinction. In Python3, the 'received' variable is of type Bytes and thus needs to be converted to string first via the use of str(). However, str() needs an encoding parameter. What would the default one be for python 2? I've tried several different encodings (latin-1 and such) but they seem to not match up with a magic value that is defined here after being unpacked here
"\xffSMB seems to decode correctly while "\xfeSMB does not.
I have adjusted the non_polling_read function and the NetBIOSSessionPacket class as follows. Full modified source code available on GitHub.
def non_polling_read(self, read_length, timeout):
data = b''
bytes_left = read_length
while bytes_left > 0:
try:
ready, _, _ = select.select([self._sock.fileno()], [], [], timeout)
if not ready:
raise NetBIOSTimeout
received = self._sock.recv(bytes_left)
if len(received) == 0:
raise NetBIOSError('Error while reading from remote', ERRCLASS_OS, None)
data = data + received
bytes_left = read_length - len(data)
except select.error as ex:
if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
raise NetBIOSError('Error occurs while reading from remote', ERRCLASS_OS, ex[0])
return data
class NetBIOSSessionPacket:
def __init__(self, data=0):
self.type = 0x0
self.flags = 0x0
self.length = 0x0
if data == 0:
self._trailer = ''
else:
try:
self.type = data[0]
if self.type == NETBIOS_SESSION_MESSAGE:
self.length = data[1] << 16 | (unpack('!H', data[2:4])[0])
else:
self.flags = data[1]
self.length = unpack('!H', data[2:4])[0]
self._trailer = data[4:]
except Exception as e:
import traceback
traceback.print_exc()
raise NetBIOSError('Wrong packet format ')
When I start the server and issue 'smbclient -L 127.0.0.1 -d 4' from the commandline, the server first creates a libs.nmb.NetBIOSTCPSession which appears to be working well. Once it tries to unwrap the libs.nmb.NetBIOSSessionPacket, it throws an exception.
Traceback (most recent call last):
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3975, in processRequest
packet = smb.NewSMBPacket(data=data)
File "/root/PycharmProjects/HoneySMB/libs/smb.py", line 690, in __init__
Structure.__init__(self, **kargs)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 77, in __init__
self.fromString(data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 144, in fromString
self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 288, in unpack
raise Exception("Unpacked data doesn't match constant value %r should be %r" % (data, answer))
Exception: ("Unpacked data doesn't match constant value b'\\xffSMB' should be 'ÿSMB'", 'When unpacking field \'Signature | "ÿSMB | b\'\\xffSMBr\\x00\\x00\\x00\\x00\\x18C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\x00\\x00\\x00\\x00\\x00\\xb1\\x00\\x02PC NETWORK PROGRAM 1.0\\x00\\x02MICROSOFT NETWORKS 1.03\\x00\\x02MICROSOFT NETWORKS 3.0\\x00\\x02LANMAN1.0\\x00\\x02LM1.2X002\\x00\\x02DOS LANMAN2.1\\x00\\x02LANMAN2.1\\x00\\x02Samba\\x00\\x02NT LANMAN 1.0\\x00\\x02NT LM 0.12\\x00\\x02SMB 2.002\\x00\\x02SMB 2.???\\x00\'[:4]\'')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3597, in handle
resp = self.__SMB.processRequest(self.__connId, p.get_trailer())
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3979, in processRequest
packet = smb2.SMB2Packet(data=data)
File "/root/PycharmProjects/HoneySMB/libs/smb3structs.py", line 435, in __init__
Structure.__init__(self,data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 77, in __init__
self.fromString(data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 144, in fromString
self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 288, in unpack
raise Exception("Unpacked data doesn't match constant value %r should be %r" % (data, answer))
Exception: ("Unpacked data doesn't match constant value b'\\xffSMB' should be 'þSMB'", 'When unpacking field \'ProtocolID | "þSMB | b\'\\xffSMBr\\x00\\x00\\x00\\x00\\x18C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\x00\\x00\\x00\\x00\\x00\\xb1\\x00\\x02PC NETWORK PROGRAM 1.0\\x00\\x02MICROSOFT NETWORKS 1.03\\x00\\x02MICROSOFT NETWORKS 3.0\\x00\\x02LANMAN1.0\\x00\\x02LM1.2X002\\x00\\x02DOS LANMAN2.1\\x00\\x02LANMAN2.1\\x00\\x02Samba\\x00\\x02NT LANMAN 1.0\\x00\\x02NT LM 0.12\\x00\\x02SMB 2.002\\x00\\x02SMB 2.???\\x00\'[:4]\'')
Now it's obvious why this throws an exception. After all, 0xFF does NOT equal ÿ or þ. The question is why is 0xFF the value it tries to write in there in the first place when it should be two different values?
The original python 2 code seems to be quite close to C (using unpack and importing cstring). Is there an obvious benefit to this here or could this be done more simply?
My actual question is:
In the original code, there is no reference to any encoding anywhere. So how is this divined then? Where does it translate 0xFF to ÿ?

Snap7 get_real command not working, how to fix?

client = snap.client.Client()
client.connect('XXX.XXX.X.XXX', 0, 2) #IP address, rack, slot
db = client.db_get(20)
print(db)
intDB = []
for i in range(1, 122):
reading = client.db_read(20, i, 1)
realReading = snap.util.get_real(reading, 0)
array = [realReading]
intDB.append(array)
print(intDB)
This code is supposed to print a DB in bytearrays and then print an array with the floats values of the PLC output. However, when I run the code, I get the following error message:
Traceback (most recent call last):
File "C:/Users/Asus/PycharmProjects/PLC-Connection/main.py", line 19, in <module>
realReading = snap.util.get_real(reading, 0)
File "C:\Users\Asus\PycharmProjects\PLC-Connection\venv\lib\site-packages\snap7\util.py", line 357, in get_real
real = struct.unpack('>f', struct.pack('4B', *x))[0]
struct.error: pack expected 4 items for packing (got 1)
I think that the problem is reading the data:
reading = client.db_read(20, i, 1)
20 is the datablock, i is the index, and you read only 1 byte (3rd parameter).
For retrieving a real, you need 4 bytes read out.

ValueError: invalid literal for float()

I am trying to read lightware rangefinder SF11 through serial but using Raspberry, and I am not familiar with Python, but I tried this:
import time
import serial
print('Code is Running.')
# Make a connection to the com port.
serialPortName = '/dev/ttyUSB0'
serialPortBaudRate = 115200
port = serial.Serial(serialPortName, serialPortBaudRate, timeout=0.1)
port.write('www\r\n')
port.readline() # Read and ignore any unintended responses
port.write('?\r\n') # Get the product information
productInfo = port.readline()
print('Product information: ' + productInfo)
while True:
port.write('LD\r\n') # reading distance (First return, default filtering)
distanceStr = port.readline()
distanceCM = float(distanceStr) * 100 # Convert the distance string into a number
print(distanceCM)
time.sleep(0.05) # Wait for 50ms before the next reading
When I run the code it's turn this:
Traceback (most recent call last):
File "range.py", line 25, in <module>
distanceCM = float(distanceStr) * 100 # Convert the distance string into a number
ValueError: invalid literal for float(): 1.72 m 0.086 V

Packet capture with python

I am trying to use dpkt and pcapy to listen for HTTP responses on an interface
import dpkt
import pcapy
cap = pcapy.open_live('eth0',10000,1,0)
(header,payload) = cap.next()
while header:
packet = dpkt.ethernet.Ethernet(str(payload))
if str(packet.data.data.data).startswith('HTTP'):
h = dpkt.http.Response(str(packet.data.data.data))
(header,payload) = cap.next()
When I run this, it reads the first packet fine. But for the second packet, it ends up reading a wrong value of content-length. The exception is:
cona#vm-02:~$ sudo python cache-pcapy.py
Value of N 160 value of body 160
Value of N 5965717 value of body 1193
Traceback (most recent call last):
File "cache-pcapy.py", line 12, in <module>
h = dpkt.http.Response(str(packet.data.data.data))
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 76, in __init__
self.unpack(args[0])
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 159, in unpack
Message.unpack(self, f.read())
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 90, in unpack
self.body = parse_body(f, self.headers)
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 59, in parse_body
raise dpkt.NeedData('short body (missing %d bytes)' % (n - len(body)))
dpkt.dpkt.NeedData: short body (missing 5964524 bytes)
The prints for values of N and length of body are from http.py in dpkt where I added this:
elif 'content-length' in headers:
n = int(headers['content-length'])
body = f.read(n)
print 'Value of N {} value of body {}'.format(n,len(body))
if len(body) != n:
raise dpkt.NeedData('short body (missing %d bytes)' % (n - len(body)))
It seems that the wrong bytes are being read as content-length. Why does this happen?

Categories

Resources