0

I'm working on making this Netcat replacement work. It's not my code, but I would like to fix it. Here's the code:

import socket


class Netcat:
    """ Python 'netcat like' module """

    def __init__(self, ip, port):
        self.buff = ""
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.connect((ip, port))

    def read(self, length = 1024):
        """ Read 1024 bytes off the socket """
        return self.socket.recv(length)
 
    def read_until(self, data):
        """ Read data into the buffer until we have data """
        while not data in self.buff:
            self.buff += self.socket.recv(1024)
 
        pos = self.buff.find(data)
        rval = self.buff[:pos + len(data)]
        self.buff = self.buff[pos + len(data):]
 
        return rval
 
    def write(self, data):
        self.socket.send(data)
    
    def close(self):
        self.socket.close()


# start a new Netcat() instance
nc = Netcat('192.168.0.1', 80)

# get to the prompt
nc.read_until('>')

# start a new note
nc.write('new' + '\n')
nc.read_until('>')

I've tried adding a new line above line 24 and encoding the string (using .encode('utf-8')), but that didn't work. Any ideas? I believe the issue is something to do with how socket recv/send operations return/accept byte objects instead of strings, but I don't know how.

user3840170
  • 26,597
  • 4
  • 30
  • 62
  • 2
    Which is line 24? What are you trying to do? What line did you add? What didn't work exactly? – interjay Jan 14 '23 at 13:22
  • @interjay Line 24 is ```self.buff += self.socket.recv(1024)```. I tried adding ```self.buff = self.buff.encode('utf-8')``` directly above it. Here's a link to the error message: https://imgur.com/a/f7s8Wh3 – frosted flakes Jan 14 '23 at 13:32
  • Reading from a socket inherently reads bytes. If you want to concatenate those in a loop, either the conversion has to happen **before** concatenating to a string, or else concatenate **to `bytes`**. Also: `.encode` means going **from** string **to** bytes. If you have bytes being read, and you want to make a string, that is `.decode`. – Karl Knechtel Jan 14 '23 at 14:16
  • `self.buff` shouldn't be initialized with a `str` value in the first place. `self.buff = b""`. Neither of the duplicate captures this aspect of the problem. – chepner Jan 14 '23 at 14:18
  • I tried to give the best-matching duplicate links I could find. Unforunately, the reference questions for all the `str` and `bytes` topics are a mess, because they mostly were asked in an era when people were madly trying to convert 2.x code to 3.x while not understanding any of the fundamentals about **what text even is**; and it's rather too late to clean up now since 2.x is 3 years past EOL. – Karl Knechtel Jan 14 '23 at 14:20
  • Other methods should also take `bytes` values as arguments instead of `str`s: `nc.read_until(b'>')`, `nc.write(b'new\n')`, etc. – chepner Jan 14 '23 at 14:20
  • @chepner absent a concrete requirement for the final result beyond "make it not raise an exception", that's a bit opinionated. Converting bytes to str works perfectly well in order to proceed with concatenating to str, and I see nothing that demands `read_until` return a `bytes`. That said, if you have better links please provide them. – Karl Knechtel Jan 14 '23 at 14:22
  • There's no reason for this class to do that, however. Let it deal with the raw data from the socket, and let a consumer convert the final result to a `str` when and if necessary. – chepner Jan 14 '23 at 15:13

0 Answers0