Client
如何構造 Ping 消息
我正在努力弄清楚如何發送基本的“PING”消息,並收到“PONG”響應。
import random import hashlib import socket PEER_IP = "35.187.200.6" PEER_PORT = 8333 nonce = (random.getrandbits(64)).to_bytes(8, byteorder="little", signed=False) magic_number = bytes.fromhex("f9beb4d9") command_name = bytes.fromhex("ping".encode("utf-8").hex() + ("00")*8) payload_size = (int(len(nonce))).to_bytes(4, byteorder="little", signed=False) checksum = hashlib.sha256(hashlib.sha256(nonce).digest()).digest()[:4] final_msg = ( magic_number + command_name + payload_size + checksum + nonce ) sock = socket.socket() sock.connect((PEER_IP, PEER_PORT)) sock.send(final_msg) pong = sock.recv(1024) print(pong)
我正在關注這個YouTube教程,並自己添加了套接字層。
我得到的唯一回應是
b''
任何洞察我在這裡做錯了什麼,將不勝感激。
謝謝
在發送其他任何內容之前,您需要發送一條
version
消息(並接收通訊者)。verack
這是處理版本消息的腳本的快速修補版本:import hashlib import random import socket import time import urllib.request PEER_IP = "127.0.0.1" PEER_PORT = 8333 nonce = (random.getrandbits(64)).to_bytes(8, byteorder="little", signed=False) magic_number = bytes.fromhex("f9beb4d9") command_name = bytes.fromhex("ping".encode("utf-8").hex() + ("00")*8) payload_size = (int(len(nonce))).to_bytes(4, byteorder="little", signed=False) checksum = hashlib.sha256(hashlib.sha256(nonce).digest()).digest()[:4] pong_msg = ( magic_number + command_name + payload_size + checksum + nonce ) # Magic bytes, as usual magic = bytes.fromhex('f9beb4d9') # Version number (PROTOCOL_VERSION in core) version = int(70015).to_bytes(4, 'little') # Random services, we don't care services = int(1).to_bytes(8, 'little') timestamp = int(time.time()).to_bytes(8, 'little') myip_str = urllib.request.urlopen('https://api.ipify.org').read().decode() myip = socket.inet_aton(myip_str) nodeip = socket.inet_aton(PEER_IP) # https://en.bitcoin.it/wiki/Protocol_documentation#Network_address addr_recv = services + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff' addr_recv += nodeip + int(8333).to_bytes(2, 'big') addr_from = services + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff' addr_from += myip + int(8333).to_bytes(2, 'big') nonce = 0x00.to_bytes(8, 'little') # You can replace this with something more fun user_agent = 0x00.to_bytes(1, 'big') # Let's say zero, once again we don't care for this example start_height = 0x00.to_bytes(4, 'little') # The message content, which we'll compute the checksum from payload = version + services + timestamp + addr_recv + addr_from + nonce payload += user_agent + start_height checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[:4] payload_length = len(payload) # The command type, as NULL padded ascii version_message = magic + 'version'.encode('ascii') + b'\x00\x00\x00\x00\x00' version_message += payload_length.to_bytes(4, 'little') + checksum + payload sock = socket.socket() sock.connect((PEER_IP, PEER_PORT)) print('Sending version message..',) sock.send(version_message) print('Received verack: {}'.format(sock.recv(24)), end='\n\n') print('Sending ping..') sock.send(pong_msg) print('Received pong: {}'.format(sock.recv(1024)))
這是我的節點的範例輸出:
Sending version message.. Received verack: b'\xf9\xbe\xb4\xd9version\x00\x00\x00\x00\x00h\x00\x00\x00n\x8a\xbe\xc7' Sending ping.. Received pong: b'\x7f\x11\x01\x00\r\x04\x00\x00\x00\x00\x00\x00\x86\xc5\x08^\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe7\xa0vQ\x16V\xb1\xab\x12/Satoshi:0.19.0.1/\x14P\t\x00\x01\xf9\xbe\xb4\xd9verack\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\xf6\xe0\xe2'
這是協議文件,您可以依靠它來實現協議消息。