houazy
houazy

Reputation: 47

Sending Custom Packet Structure with data from a file

I am trying to send a packet with 20 byte checksum, 10 byte sequence and 482 bytes of a file that it reads from. This is what I have below. How do I send the packet with all that info and how does the server know what is what?

import socket
import hashlib

buffer_size = 482
port = 5900
file = open('helloworld.txt', 'rb')
transfer = file.read(buffer_size)
hash_object = hashlib.sha1(transfer)
checksum = hash_object.hexdigest()
addr = ('localhost', port)
sock = socket.socket()
sock.connect(addr)
print('Connected to', addr)
sock.sendto((checksum + transfer))
file.close()
print("File sent")
sock.close()
sock.send()

Upvotes: 0

Views: 1032

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177554

Define a byte-oriented protocol for the TCP data stream. Your "10-byte sequence" data wasn't demonstrated, so I'll make one up for illustration. For example:

  1. Send the transfer size as a 2-byte big-endian value.
  2. Send the 20-byte SHA1 digest of the transfer data.
  3. Send the transfer data

Example:

import socket
import hashlib
import struct
import os

buffer_size = 482
port = 8000
transfer = os.urandom(buffer_size) # generate some data
hash_object = hashlib.sha1(transfer)
checksum = hash_object.digest() # digest (not hexdigest) is a 20-byte string.
addr = 'localhost', port
sock = socket.socket()
sock.connect(addr)
print('Connected to', addr)
sock.sendall(struct.pack('>H',buffer_size) + checksum + transfer)
print("File sent")
sock.close()

A receiving server could look like the following. Note that TCP is a byte streaming protocol, so a blocking recv(2048) could return 0 (socket closed) or 1-2048 bytes. I purposefully picked a small, odd value for receiving to demonstrate that you should buffer reads and extract data according to the protocol. This example doesn't handle if the data stream ends early.

import socket
import struct
import hashlib

class Buffer:

    def __init__(self,sock):
        self.sock = sock
        self.buffer = b''

    def get(self,length):
        # Make sure enough bytes to satisfy the length requested
        # are in the buffer.
        while len(self.buffer) < length:
            data = self.sock.recv(7)
            if not data: break
            self.buffer += data
        # Split off from the current buffer the bytes requested.
        # Keep the remainder for the next request.
        rcv,self.buffer = self.buffer[:length],self.buffer[length:]
        return rcv

s = socket.socket()
s.bind(('',8000))
s.listen(1)
c,a = s.accept()
buf = Buffer(c)
length = struct.unpack('>H',buf.get(2))[0]
chksm = buf.get(20)
transfer = buf.get(length)
verify = hashlib.sha1(transfer)
print(chksm == verify.digest())  # should be "True"
c.close()
s.close()

Upvotes: 1

Related Questions