I am sending a request to a tracker and get a response
d8:completei2e10:downloadedi1e10:incompletei1e8:intervali1971e12:min intervali985e5:peers18:\235'\027\253\000\000\331e57\374-\033"\022,\270\302e
How to get Peers list or peer IP and port from this response
The response from the tracker is bencoded.
Adding some whitespace for clarity:
d
8:complete
i2e
10:downloaded
i1e
10:incomplete
i1e
8:interval
i1971e
12:min interval
i985e
5:peers
18:\235'\027\253\000\000\331e57\374-\033"\022,\270\302
e
The key:peers that has a 18 bytes binary string as value contains peers in the 'compact=1'-form that is specified in: [BEP23 - Tracker Returns Compact Peer Lists] and also in [the wiki]
Every peer is represented by 6 bytes, 4 bytes IPv4 + 2 bytes PORT in bigendian, so the 18 bytes string is for 3 peers.
\235 ' \027 \253 \000 \000=>157 39 23 171 0 0(0*256+0=0) =>157.39.23.171:0
\331 e 5 7 \374 - =>227 101 53 55 252 45(252*256+45=64557)=>227.101.53.55:64557
\033 " \022 , \270 \302=>27 34 18 44 184 192(184*256+192=47298)=>27.34.18.44:47298
(\235 is octal for 157, ' has ASCII value 39 etc.)
Related
[SOLVED] Could someone help on this? I use minimalmodbus on python 3.11.1 to query a USB<->RS485 transceiver (see picture below) that is connected to a PZEM-016 (for measuring AC power consumption: voltage, current, power, energy, frequency...).
When used with the Simply Modbus Master 8.1.2, I can read the data without any problem.
With Python and minimalmodbus, I can only get up to 7 registers and of course the data is wrong (I can't pass the 7th register).
Here is the code
import minimalmodbus
#######################################
# CONSTANTS declaration
#######################################
# Communication constants
PORT_NAME ='COM3'
BAUD_RATE = 9600
BYTE_SIZE = 8
STOP_BITS = 1
TIMEOUT_VAL = 0.7
SLAVE_ADDR = 1
READ_MODE_NB = 4 # minimalmodus default to 3 PZEM requires 4 or it issues an error
WRITE_FCT_NB = 16 #HEX: 0x10
DEBUG_VAL = True
ECHO_VAL = False # Changed back from True to False after solution found
# Register constants
BASE_REG = 0
VOLT_REG = 0 #0x0000
CURR_LOW_REG = 1 #0x0001
CURR_HIGH_REG = 2 #0x0002
POWER_LOW_REG = 3 #0x0003
POWER_HIGH_REG = 4 #0x0004
ENGY_LOW_REG = 5 #0x0005
ENGY_HIGH_REG = 6 #0x0006
FREQCY_REG = 7 #0x0007
POWER_FACTOR_REG = 8 #0x0008
ALARM_REG = 9 #0x0009
#######################################
# Variables initialization
#######################################
instrument = ''
response = ''
voltage = ''
current_high = ''
current_low = ''
power_high = ''
power_low = ''
energy_high = ''
energy_low = ''
frequency = ''
power_factor = ''
alarm_status = ''
#######################################
# Set up the instrument
#######################################
instrument = minimalmodbus.Instrument(PORT_NAME, SLAVE_ADDR)
#######################################
# Explicit instrument settings
#######################################
instrument.serial.baudrate = BAUD_RATE # baud rate
instrument.serial.bytesize = BYTE_SIZE # data bits
instrument.serial.parity = minimalmodbus.serial.PARITY_NONE # parity
instrument.serial.stopbits = STOP_BITS # stop bit
instrument.serial.timeout = TIMEOUT_VAL # seconds
instrument.mode = minimalmodbus.MODE_RTU # communication protocol
# instrument.address = SLAVE_ADDR # slave address when only one slave in the bus
instrument.debug = DEBUG_VAL
instrument.handle_local_echo = ECHO_VAL
instrument.close_port_after_each_call = True
instrument.clear_buffers_before_each_transaction = True
#######################################
# Typical request format of the master
# Slave address: x001
# Command type: 0x04
# First register address high = left bytes: 0x00
# First register address low = right bytes: 0x00 (=> 0x0000 = 0)
# Number of registers high = left bytes: 0x00
# Number of registers low = right bytes: 0x0A (=> 0x000A = 10)
# CRC check high = left bytes: 0x70
# CRC check low = right bytes: 0x0D (=> 0x700D)
# 01 04 00 00 00 0A 70 0D
# Typical reply format of the slave
# Slave address: 0x01
# Command type: 0x04
# Number of bytes: 0x14 (= 20 bytes = 2 bytes per requested register)
# Register 1: Voltage 8 bits
# Register 1 data high byte = left byte: 0x09
# Register 1 data low byte = right byte: 0x2E (=> 0x092E = 2350 = 235.0V)
# Register 2 + 3: Current 16 bits
# Register 2 data low byte = right bits: 0x01
# Register 2 data high byte = left bits: 0x78
# Register 3 data low byte = right bits: 0x00
# Register 3 data high byte = left bits: 0x00 (=> 0x00000178 = 376 = 0.376A)
# Register 4 + 5: Power 16 bits
# Register 4 data low byte = right bits: 0x01
# Register 4 data high byte = left bits: 0xE7
# Register 5 data low byte = right bits: 0x00
# Register 5 data high byte = left bits: 0x00 (=> 0x000001E7 = 487 = 48.7W)
# Register 6 + 7: Energy 16 bits
# Register 6 data low byte = right bits: 0x02
# Register 6 data high byte = left bits: 0xEA
# Register 7 data low byte = right bits: 0x00
# Register 7 data high byte = left bits: 0x00 (=> 0x000002EA = 746 = 746Wh)
# Register 8: Frequency 8 bits
# Register 8 data high byte = left byte: 0x01
# Register 8 data low byte = right byte: 0xF4 (=> 0x01F4 = 500 = 50.0Hz)
# Register 9: Power factor 8 bits
# Register 9 data high byte = left byte: 0x00
# Register 9 data low byte = right byte: 0x37 (=> 0x0037 = 55 = 0.55)
# Register 10: Alarm status 8 bits
# Register 10 data high byte = left byte: 0x00
# Register 10 data low byte = right byte: 0x00 (=> 0x0000 = 0 = No alarm)
# CRC check high = left bytes: 0xE5 (= 229)
# CRC check low = right bytes: 0xFD (= 253) (=> 0xE5FD)
# LED lights turned on
# 01 04 14 09 2E 01 78 00 00 01 E7 00 00 02 EA 00 00 01 F4 00 37 00 00 39 51
# LED lights turned off
# 01 04 14 09 34 00 00 00 00 00 05 00 00 02 E4 00 00 01 F3 00 64 00 00 E5 FD
#######################################
print('instrument: ', instrument)
#######################################
# Read and print registers' data
#######################################
response = instrument.read_registers(VOLT_REG, 10, READ_MODE_NB)
print('Response raw: ', response)
With the wrong read mode value, I get an error message with the read_registers() command
>>> ReadSerial.py
< MinimalModbus debug mode. Will write to instrument (expecting 25 bytes back): 01 03 00 00 00 0A C5 CD (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port COM3
MinimalModbus debug mode. No sleep required before write. Time since previous read: 167521078.00 ms, minimum silent period: 4.01 ms.
MinimalModbus debug mode. Closing port COM3
MinimalModbus debug mode. Response from instrument: 01 83 02 C0 F1 (5 bytes), roundtrip time: 0.8 ms. Timeout for reading: 700.0 ms.
< Traceback (most recent call last):
File "...\ReadSerial.py", line 127, in <module>
response = instrument.read_registers(VOLT_REG, 10, READ_MODE_NB)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\minimalmodbus.py", line 904, in read_registers
returnvalue = self._generic_command(
^^^^^^^^^^^^^^^^^^^^^^
File "...\minimalmodbus.py", line 1245, in _generic_command
payload_from_slave = self._perform_command(functioncode, payload_to_slave)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "...\minimalmodbus.py", line 1329, in _perform_command
payload_from_slave = _extract_payload(
^^^^^^^^^^^^^^^^^
File "...\minimalmodbus.py", line 1880, in _extract_payload
_check_response_slaveerrorcode(response)
File "...\minimalmodbus.py", line 3538, in _check_response_slaveerrorcode
raise error
minimalmodbus.IllegalRequestError: Slave reported illegal data address
I matched everything I could with the Simply Modbus Master example, except for the query mode, which value should be 4 (minimalmodbus default read mode is 3).
Update from above
I finally found the error in my code, which was very stupid, but errors are often stupid like a missing ";".
I still have to figure out why the read_register() command doesn't work (without the "s" for reading one register at a time). I can't pass the 7th register without errors and the returned data is wrong.
I leave the question and the answer for the community, in case someone uses the same PZEM-014 -> PZEM0-17 and looks for a python solution to retrieve the data
I'm porting a game server to NodeJS. The problem is that I'm not familiar at all with packets and building them out. After reading through the NodeJS docs, I think that I've structured my response the way that the client expects, but I'm the client doesn't seem to respond well to what my server is sending.
Hoping someone can confirm that it's something in my server response that doesn't match the documentation requirements..
The client expects the following response from the TCP socket:
Packet Build
BYTE[1] cmd (0xA8)
BYTE[2] total length of this packet
BYTE[1] System Info Flag (0x5D)
BYTE[2] # of servers
(Repeat as needed for each server)
BYTE[2] server index (0-based)
BYTE[32] server name
BYTE percent full
BYTE timezone
BYTE[4] server IP to ping
Here is my NodeJS interpretation of the docs.
/** Build response header */
const length = 45
serverResponse = Buffer.alloc(length)
serverResponse.fill(0xA8, 0)
serverResponse.fill(Buffer.alloc(2, length), 1)
// Last fill had a buffer size of 2, so our next offset considers that
serverResponse.fill(0x5d,3)
serverResponse.fill(Buffer.alloc(2, 1),4)
/** Build response server list */
serverResponse.fill(Buffer.alloc(2, 0),5) /* 2 Bytes (server index, 0-based) */
// Last fill had a buffer size of 2, so our next offset considers that
serverResponse.fill(
Buffer.alloc(32, Buffer.from('Heres your server')),
7) /* 32 bytes (Server name) */
serverResponse.fill(Buffer.alloc(1, 9), 39) /* 1 Bytes (% Full) */
/**
* Trying -12 - 12 range divided by (60 * 60)). #see
* https://github.com/Sphereserver/Source/blob/0be2bc1d2e16659239460495b9819eb8dcfd39ed/src/graysvr/CServRef.cpp#L42
*/
serverResponse.fill(Buffer.alloc(1, -5 / (60 *60)),40) /* 1 Bytes (Timezone */
serverResponse.fill(Buffer.from([0,0,0,0]), 41) /** IP Address */
This outputs:
<Buffer a8 2d 2d 5d 01 00 00 48 65 72 65 73 20 79 6f 75 72 20 73 65 72 76 65 72 48 65 72 65 73 20 79 6f 75 72 20 73 65 72 76 09 00 00 00 00 00>
Edit: I've discovered the following that may help me along.
NodeJS equivalents
/**
* BYTE 8-bit unsigned buf.writeUInt8()
* SBYTE 8-bit signed buf.writeInt8()
* BOOL 8-bit boolean (0x00=False, 0xFF=True) buf.fill(0x00) || buf.fill(0xFF)
* CHAR 8-bit single ASCII character buf.from('Text', 'ascii') - Make 8-bit?
* UNI 16-bit single unicode character buf.from('A', 'utf16le') - Correct?
* SHORT 16-bit signed buf.writeInt16BE() - #see https://www.reddit.com/r/node/comments/9hob2u/buffer_endianness_little_endian_or_big_endian_how/
* USHORT 16-bit unsigned buf.writeUInt16BE() - #see https://www.reddit.com/r/node/comments/9hob2u/buffer_endianness_little_endian_or_big_endian_how/
* INT 32-bit signed buf.writeInt32BE - #see https://www.reddit.com/r/node/comments/9hob2u/buffer_endianness_little_endian_or_big_endian_how/
* UINT 32-bit unsigned buf.writeUInt32BE - #see https://www.reddit.com/r/node/comments/9hob2u/buffer_endianness_little_endian_or_big_endian_how/
*/
Below is the ip_options_build() in linux kernel 3.4, line 51 and 52:
51 if (opt->srr)
52 memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);
I understand that the two lines say, if source routing option is present, copy the destination address to the end of the option, that suggests that iph[opt->srr+1] is the length of the source routing option, but I don't get it why?
31/*
32 * Write options to IP header, record destination address to
33 * source route option, address of outgoing interface
34 * (we should already know it, so that this function is allowed be
35 * called only after routing decision) and timestamp,
36 * if we originate this datagram.
37 *
38 * daddr is real destination address, next hop is recorded in IP header.
39 * saddr is address of outgoing interface.
40 */
41
42void ip_options_build(struct sk_buff *skb, struct ip_options *opt,
43 __be32 daddr, struct rtable *rt, int is_frag)
44{
45 unsigned char *iph = skb_network_header(skb);
46
47 memcpy(&(IPCB(skb)->opt), opt, sizeof(struct ip_options));
48 memcpy(iph+sizeof(struct iphdr), opt->__data, opt->optlen);
49 opt = &(IPCB(skb)->opt);
50
51 if (opt->srr)
52 memcpy(iph+opt->srr+iph[opt->srr+1]-4, &daddr, 4);
53
54 if (!is_frag) {
55 if (opt->rr_needaddr)
56 ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, skb, rt);
57 if (opt->ts_needaddr)
58 ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt);
59 if (opt->ts_needtime) {
60 struct timespec tv;
61 __be32 midtime;
62 getnstimeofday(&tv);
63 midtime = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC
+ tv.tv_nsec / NSEC_PER_MSEC);
64 memcpy(iph+opt->ts+iph[opt->ts+2]-5, &midtime, 4);
65 }
66 return;
67 }
68 if (opt->rr) {
69 memset(iph+opt->rr, IPOPT_NOP, iph[opt->rr+1]);
70 opt->rr = 0;
71 opt->rr_needaddr = 0;
72 }
73 if (opt->ts) {
74 memset(iph+opt->ts, IPOPT_NOP, iph[opt->ts+1]);
75 opt->ts = 0;
76 opt->ts_needaddr = opt->ts_needtime = 0;
77 }
78}
If I remember correctly, iph + opt->srr is basically the address of the first byte of the srr option. The format of the option itself is as follows:
TYPE (1 byte) | LENGTH (1 byte) | OFFSET (1 byte) | ... and then some addresses 4 bytes each
The LENGTH "field" specifies the length in bytes of the entire option, so that's why iph[opt->srr+1] is the length of the option.
I run snmpwak -v2c -c public switchname .1.3.6.1.2.1.17.4.3.1.1 as per instrucion in http://www.cisco.com/en/US/tech/tk648/tk362/technologies_tech_note09186a00801c9199.shtml.
I got lots of Hex-String and String.
Hex-STRINGs like this:
SNMPv2-SMI::mib-2.17.4.3.1.1.244.109.4.97.116.234 = Hex-STRING: F4 6D 04 61 74 E0
STRINGs like these:
SNMPv2-SMI::mib-2.17.4.3.1.1.44.39.215.46.139.92 = STRING: ",'×.<\\"
SNMPv2-SMI::mib-2.17.4.3.1.1.44.39.215.46.142.98 = STRING: ",'×.Zb"
SNMPv2-SMI::mib-2.17.4.3.1.1.44.39.215.46.145.38 = STRING: ",'×.'&"
Some Macs can be found in Hex-STRING, but others can't. Maybe are some Macs hidden in STRING? How can I convert these STRING to HEX?
The six decimal values in the MIB after mib-2.17.4.3.1.1 is indeed the MAC address in decimal form.
SNMPv2-SMI::mib-2.17.4.3.1.1.44.39.215.46.139.92
44 (2c) 39 (27) 215 (d7) 46 (2e) 139 (8b) 92 (5c)
2c:27:d7:2e:8b:5c OUI search: HP
Just started testing nodejs, and wanted to get some help in understanding following behavior:
Example #1:
var http = require('http');
http.createServer(function(req, res){
res.writeHeader(200, {'Content-Type': 'text/plain'});
res.end('foo');
}).listen(1001, '0.0.0.0');
Example #2:
var http = require('http');
http.createServer(function(req, res){
res.writeHeader(200, {'Content-Type': 'text/plain'});
res.write('foo');
res.end('bar');
}).listen(1001, '0.0.0.0');
When testing response time in Chrome:
example #1 - 6-10ms
example #2 - 200-220ms
But, if test both examples through nginx proxy_pass
server{
listen 1011;
location / {
proxy_pass http://127.0.0.1:1001;
}
}
i get this:
example #1 - 4-8ms
example #2 - 4-8ms
I am not an expert on either nodejs or nginx, and asking if someone can explain this?
nodejs - v.0.8.1
nginx - v.1.2.2
update:
thanks to Hippo, i made test with ab on my server with and without nginx,
and got opposite results.
also added to nginx config proxy_cache off
server{
listen 1011;
location / {
proxy_pass http://127.0.0.1:1001;
proxy_cache off;
}
}
example #1 direct:
ab -n 1000 -c 50 http:// 127.0.0.1:1001/
Server Software:
Server Hostname: 127.0.0.1
Server Port: 1001
Document Path: /
Document Length: 65 bytes
Concurrency Level: 50
Time taken for tests: 1.018 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 166000 bytes
HTML transferred: 65000 bytes
Requests per second: 981.96 [#/sec] (mean)
Time per request: 50.919 [ms] (mean)
Time per request: 1.018 [ms] (mean, across all concurrent requests)
Transfer rate: 159.18 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 3
Processing: 0 50 44.9 19 183
Waiting: 0 49 44.8 17 183
Total: 1 50 44.7 19 183
example #1 nginx:
ab -n 1000 -c 50 http:// 127.0.0.1:1011/
Server Software: nginx/1.2.2
Server Hostname: 127.0.0.1
Server Port: 1011
Document Path: /
Document Length: 65 bytes
Concurrency Level: 50
Time taken for tests: 1.609 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 187000 bytes
HTML transferred: 65000 bytes
Requests per second: 621.40 [#/sec] (mean)
Time per request: 80.463 [ms] (mean)
Time per request: 1.609 [ms] (mean, across all concurrent requests)
Transfer rate: 113.48 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 3
Processing: 2 77 44.9 96 288
Waiting: 2 77 44.8 96 288
Total: 3 78 44.7 96 288
example #2 direct:
ab -n 1000 -c 50 http:// 127.0.0.1:1001/
Server Software:
Server Hostname: 127.0.0.1
Server Port: 1001
Document Path: /
Document Length: 76 bytes
Concurrency Level: 50
Time taken for tests: 1.257 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 177000 bytes
HTML transferred: 76000 bytes
Requests per second: 795.47 [#/sec] (mean)
Time per request: 62.856 [ms] (mean)
Time per request: 1.257 [ms] (mean, across all concurrent requests)
Transfer rate: 137.50 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 2
Processing: 0 60 47.8 88 193
Waiting: 0 60 47.8 87 193
Total: 0 61 47.7 88 193
example #2 nginx:
ab -n 1000 -c 50 http:// 127.0.0.1:1011/
Server Software: nginx/1.2.2
Server Hostname: 127.0.0.1
Server Port: 1011
Document Path: /
Document Length: 76 bytes
Concurrency Level: 50
Time taken for tests: 1.754 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 198000 bytes
HTML transferred: 76000 bytes
Requests per second: 570.03 [#/sec] (mean)
Time per request: 87.715 [ms] (mean)
Time per request: 1.754 [ms] (mean, across all concurrent requests)
Transfer rate: 110.22 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.4 0 2
Processing: 1 87 42.1 98 222
Waiting: 1 86 42.3 98 222
Total: 1 87 42.0 98 222
Now results looks more logic, but still there is a strange delay when calling res.write()
I guess it was (sure looks like) a stupid question, but i still get huge difference in response time in browser with this server configuration (Centos 6) and this concrete server (vps).
On my home computer (Ubuntu 12) but with older versions testing from localhost everything works fine.
Peeking into http.js reveals that case #1 has special handling in nodejs itself, some kind of a shortcut optimization I guess.
var hot = this._headerSent === false &&
typeof(data) === 'string' &&
data.length > 0 &&
this.output.length === 0 &&
this.connection &&
this.connection.writable &&
this.connection._httpMessage === this;
if (hot) {
// Hot path. They're doing
// res.writeHead();
// res.end(blah);
// HACKY.
if (this.chunkedEncoding) {
var l = Buffer.byteLength(data, encoding).toString(16);
ret = this.connection.write(this._header + l + CRLF +
data + '\r\n0\r\n' +
this._trailer + '\r\n', encoding);
} else {
ret = this.connection.write(this._header + data, encoding);
}
this._headerSent = true;
} else if (data) {
// Normal body write.
ret = this.write(data, encoding);
}
if (!hot) {
if (this.chunkedEncoding) {
ret = this._send('0\r\n' + this._trailer + '\r\n'); // Last chunk.
} else {
// Force a flush, HACK.
ret = this._send('');
}
}
this.finished = true;
I've took you examples files and used ab (Apache Benchmark) as a proper tool for benchmarking HTTP server performance:
Example 1:
Concurrency Level: 50
Time taken for tests: 0.221 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 104000 bytes
HTML transferred: 3000 bytes
Requests per second: 4525.50 [#/sec] (mean)
Time per request: 11.049 [ms] (mean)
Time per request: 0.221 [ms] (mean, across all concurrent requests)
Transfer rate: 459.62 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.7 0 4
Processing: 1 11 6.4 10 32
Waiting: 1 11 6.4 10 32
Total: 1 11 6.7 10 33
Example 2:
Concurrency Level: 50
Time taken for tests: 0.256 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 107000 bytes
HTML transferred: 6000 bytes
Requests per second: 3905.27 [#/sec] (mean)
Time per request: 12.803 [ms] (mean)
Time per request: 0.256 [ms] (mean, across all concurrent requests)
Transfer rate: 408.07 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.6 0 4
Processing: 1 12 7.0 12 34
Waiting: 1 12 6.9 12 34
Total: 1 12 7.1 12 34
Note:
The second example is as fast as the first one. The small differences are probably caused by the the additional function call in the code and the fact that the document size is larger then with the first one.