I've made a simple netcat in Python and would appreciate any advice/opinions of how I've implemented it.
test.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import netcat
def main(*args):
netcat.connect('localhost', 4444)
netcat.listen('', 4444)
if __name__ == '__main__':
sys.exit(main(*sys.argv))
netcat.py:
# -*- coding: utf-8 -*-
import sys
import select
import socket
from contextlib import closing
from servers import Server
from cat import cat_line
def netcat(sock, infile=sys.stdin, outfile=sys.stdout):
with closing(sock) as s:
sf = s.makefile()
while True:
r, w, e = select.select([s, infile], [], [])
if s in r:
if not cat_line(sf, outfile):
break
if infile in r:
if not cat_line(infile, sf):
break
def listen(lhost, lport, *args, **kwargs):
with Server(lhost, lport) as server:
client = server.get_client()
netcat(client, *args, **kwargs)
def connect(rhost, rport, *args, **kwargs):
server = socket.create_connection((rhost, rport))
with closing(server) as s:
netcat(s, *args, **kwargs)
servers.py:
# -*- coding: utf-8 -*-
import socket
class Server(object):
def __init__(self, lhost, lport):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._sock.bind((lhost, lport))
self._sock.listen(1)
def __iter__(self):
return self
def next(self):
return self.get_client()
def __enter__(self):
return self
def __exit__(self, *exc):
self.close()
def get_client(self):
return self._sock.accept()[0]
def close(self):
self._sock.close()
cat.py:
# -*- coding: utf-8 -*-
import sys
def cat_line(infile=sys.stdin, outfile=sys.stdout):
line = infile.readline()
if not line:
return False
outfile.write(line)
outfile.flush()
return True
def cat(infile=sys.stdin, outfile=sys.stdout):
while True:
if not cat_line(infile, outfile):
break
Edit: Maybe I should take the responsibility of closing the socket from the netcat function...
def netcat(sock, infile=sys.stdin, outfile=sys.stdout):
sf = sock.makefile()
while True:
r, w, e = select.select([sock, infile], [], [])
if sock in r and not cat_line(sf, outfile):
break
if infile in r and not cat_line(infile, sf):
break
and instead, put that functionality into the listen function?
def listen(lhost, lport, *args, **kwargs):
with Server(lhost, lport) as server:
client = server.get_client()
with closing(client) as c:
netcat(c, *args, **kwargs)
Also...
def cat(infile=sys.stdin, outfile=sys.stdout):
while True:
if not cat_line(infile, outfile):
break
could be
def cat(infile=sys.stdin, outfile=sys.stdout):
while cat_line(infile, outfile):
pass