is the logic behind my trivial tftp client flawed? - python

I'm still a student so I might have missed something really obvious.
So I am stressing out about this so much.
But anyway here's my TFTP python code, all it does is downloading a text-file from our lecturer's server.
The file generated by it looks like this:
http://pastebin.com/TP8hngxM
And the original file like this:
http://pastebin.com/xDMjkABp
And if you run it through a difference checker, the difference is miniscule and in only 1 specific spot and it's really difficult for me to figure out why is this happening.
The downloaded file has a few extra words.
If you have spare 5 minutes, could you please check out my nested while loop (everything else was provided by the lecturer and can't be changed) to see if there's anything wrong with it?
The worst thing is that I've already had it working, but I lost my memory stick and I lost the most up-to-date version of the program that was running 100% fine.
So as I said, it's only about the nested while loop, I' not allowed to change anything above it.
#!/usr/bin/python
import struct
import sys
import os
import select
import glamnetsim
from socket import *
serverHost = 'mcgreg.comp.glam.ac.uk'
serverPort = 69
timeoutSecs = 5
debugging = False
RRQ, WRQ, DATA, ACK, ERROR = range(1, 6)
codeDescriptions = {RRQ:"RRQ", WRQ:"WRQ", DATA:"DATA", ACK:"ACK", ERROR:"ERROR"}
def printf (format, *args):
print str(format) % args,
def finish ():
printf("you should see\n1e951df315d433aa4df2065a1ad31311\n")
os.system("md5sum newfile.txt")
sys.exit(0)
def sendPacket (packet, port):
global sock, debugging
global serverIp
if debugging:
for i in packet:
print ('%02x' % ord(i)),
print ''
sock.sendto(packet, (serverIp, port))
def sendReadRequest (filename, mode):
global serverPort
format = "!H%ds" % (len(filename)+1)
format += "%ds" % (len(mode)+1)
s = struct.pack(format, 1, filename, mode)
sendPacket(s, serverPort)
def sendRealAck(blockno, port):
s = struct.pack("!H", 4)
s += struct.pack("!H", blockno)
sendPacket(s, port)
def sendACK (blockno, port):
print " -> ACK:%d\n" % blockno
if blockno == 0:
sendReadRequest("the_machine_stops.txt", "octet")
else:
sendRealAck(blockno, port)
def stripPacket (s):
if len(s)>3:
code = struct.unpack("!H", s[:2])[0]
blockno = struct.unpack("!H", s[2:4])[0]
data = s[4:]
code, data = glamnetsim.simulatePossibleError (code, data)
return code,blockno,data
else:
debugPrint("corrupt packet")
return -1,-1,""
def debugPrint (s):
global debugging
if debugging:
print s
def getDesc (c):
global codeDescriptions
return codeDescriptions[c]
sock = socket(AF_INET, SOCK_DGRAM)
serverIp = gethostbyname(serverHost)
sock.setblocking(1)
sendReadRequest("the_machine_stops.txt", "netascii")
lastblock = 0
blockno = 0
port = serverPort
f = open("newfile.txt", "w")
while True:
while True:
if blockno == lastblock+1:
break
r, w, x = select.select([sock], [], [], 5.0)
if r == []:
sendACK(lastblock, port)
else:
(packet, (address, port)) = sock.recvfrom(512+4)
code, newblock, text = stripPacket(packet)
print code, blockno
if code is 3:
blockno = newblock
sendACK(blockno, port)
if code is 5:
sendACK(lastblock, port)
print "Bn: " + str(blockno) + " Lb: " + str(lastblock)
lastblock = blockno
f.write(text)
print "OK"
if len(text) < 512:
break
f.close()
finish()

f.write(text)
That line is run with a stale value if blockno == lastblock+1. It probably should be within the inner loop.

Related

Python 3.4.2 - Socket module is not callable

from socket import *
import _thread
from My_TCP_callable import *
IP_list = []
port_list = []
def IP_find(IP_list):
IPtarget = input("Enter host to scan: ")
IP_list = []
print ('Starting scan on host ', IPtarget)
for ip in range(1, 256):
s = socket(AF_INET, SOCK_STREAM)
addr = IPtarget + str(ip)
result = s.connect_ex((addr, 135))
print (ip)
if(result == 0):
print ('IP %d: OPEN' % (addr,))
IP_list.append(str(addr))
s.close()
print("Open ports: %s" % (port_list))
sending_socket(port_list)
return
def port_find(port_list):
if __name__ == '__main__':
target = input('Enter host to scan: ')
possible_list = []
port_list = []
typ = int(input(" 1.Use standard ports \n 2.Set a range of points \n 3+.Set a number of specific points "))
if typ == 1:
possible_list = [20, 1025]
else:
for number in range(typ):
v = int(input("Set a port point: "))
possible_list.append(v)
if typ >= 3:
x = (possible_list)
else:
x = range(min(possible_list), max(possible_list))
targetIP = gethostbyname(target)
print ('Starting scan on host ', targetIP)
#scan reserved ports
for i in x:
s = socket(AF_INET, SOCK_STREAM)
result = s.connect_ex((targetIP, i))
if(result == 0):
print ('Port %d: OPEN' % (i,))
port_list.append(str(i))
s.close()
print("Open ports: %s" % (port_list))
return port_list
def sending_socket(port_list):
send_socket = input("Would you like to send a socket with this? ")
if send_socket == "yes":
port = int(input("Which port would you like to search? "))
message = input("What would you like to send? ")
My_TCP_callable.connect(targetIP, port, message)
elif send_socket == "automate":
message = "Alive"
for ports in port_list:
_thread.start_new_thread(connect ,(targetIP, ports, message))
return
IP_find(IP_list)
Every time I call this code an error comes up:
File "C:\Users\as009542\Desktop\python\Networking\scanner.py", line 81, in
<module>
IP_find(IP_list)
File "C:\Users\as009542\Desktop\python\Networking\scanner.py", line 15, in IP_find
s = socket(AF_INET, SOCK_STREAM)
TypeError: 'module' object is not callable
I've checked around and used this in other programs but I cant figure out why the socket can't create.
This code is not pretty or complete however I can't continue making it until I fix this problem, the last function 'sending_socket' is being called from a different file called 'My_TCP_callable' although this does not affect the problem I am having.
You are probably using import socket in your module My_TCP_callable
Because you use
from socket import *
from My_TCP_callable import *
Everything from each module is imported, and the socket names are clashing (preference is given to the one from My_TCP_callable.
I reproduced this behaviour with two files, test2.py which contained one line, import socket, and test.py which contained
from socket import *
from test2 import *
socket()
A good coding style is to use from ... import * very rarely, and only on modules specifically designed for it.

Python Multi Threading Variables getting overwritten and mixed up

It tries to make two connections per thread now, still fails.
I think I solved the shared access thing because it uses self.x instead of local variables?
I'm not sure what the problem is :/, you don't happen to be a freelancer?
#!/usr/bin/python
from xml.etree.ElementTree import fromstring
from socks import socksocket, PROXY_TYPE_SOCKS5
from socket import socket, AF_INET, SOCK_STREAM
from linecache import getline
from threading import Thread, current_thread, Lock, activeCount
from os.path import isfile, getmtime
from urllib import urlopen
from time import time, sleep
from sys import exit
from json import loads
from random import randint, randrange, choice
from urlparse import parse_qs
from pprint import pprint
class myThread (Thread):
def __init__(self, threadID, name):
Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
self.user = parse_qs(getline('./_files/ids.txt', randint(1, idLen)).strip("\n"))
self.proxy = getline('./_files/proxies.txt', randint(1, proxyLen)).strip("\n").split(":")
self.user2 = parse_qs(getline('./_files/ids.txt', randint(1, idLen)).strip("\n"))
self.proxy2 = getline('./_files/proxies.txt', randint(1, proxyLen)).strip("\n").split(":")
try:
self.socket = socksocket(AF_INET, SOCK_STREAM)
self.socket.settimeout(5)
self.socket.setproxy(PROXY_TYPE_SOCKS5, self.proxy[0], int(self.proxy[1]))
self.socket2 = socksocket(AF_INET, SOCK_STREAM)
self.socket2.settimeout(5)
self.socket2.setproxy(PROXY_TYPE_SOCKS5, self.proxy2[0], int(self.proxy2[1]))
self.socket.connect((chatConnection[0], int(chatConnection[1])))
self.socket2.connect((chatConnection[0], int(chatConnection[1])))
send(self.socket, "<y r=\"%s\" v=\"0\" u=\"%s\" />\0" % (room, self.user["UserId"][0]))
send(self.socket2, "<y r=\"%s\" v=\"0\" u=\"%s\" />\0" % (room, self.user2["UserId"][0]))
self.data = read(self.socket)
self.data2 = read(self.socket2)
if self.data == "" or not self.data: return
if self.data2 == "" or not self.data2: return
self.xml = fromstring(self.data.strip(chr(0))).attrib
self.xml2 = fromstring(self.data2.strip(chr(0))).attrib
self.bSock = socket(AF_INET, SOCK_STREAM)
self.bSock.settimeout(5)
self.bSock2 = socket(AF_INET, SOCK_STREAM)
self.bSock2.settimeout(5)
self.bSock.connect(("127.0.0.1", 1337))
send(self.bSock, "<bot p=\"%s\" yi=\"%s\" au=\"%s\" />\0" % (self.xml["p"], self.xml["i"], self.xml["au"]))
self.data = read(self.bSock)
send(self.bSock, "<bot p=\"%s\" yi=\"%s\" au=\"%s\" />\0" % (self.xml2["p"], self.xml2["i"], self.xml2["au"]))
self.data2 = read(self.bSock)
self.data = self.data.replace("_lol", "")
self.l5 = self.data[self.data.find('l5="') + 4:]
self.l5 = self.l5[:self.l5.find('"')]
self.ya = self.data[self.data.find('c="') + 3:]
self.ya = self.ya[:self.ya.find('"')]
self.data2 = self.data2.replace("_lol", "")
self.l52 = self.data2[self.data2.find('l5="') + 4:]
self.l52 = self.l52[:self.l52.find('"')]
self.ya2 = self.data2[self.data2.find('c="') + 3:]
self.ya2 = self.ya2[:self.ya2.find('"')]
print self.ya2 + " : " + self.l52
self.bSock.close()
self.yaSock = socksocket(AF_INET, SOCK_STREAM)
self.yaSock.settimeout(5)
self.yaSock.setproxy(PROXY_TYPE_SOCKS5, self.proxy[0], int(self.proxy[1]))
self.yaSock.connect((chatConnection[0], int(chatConnection[1])))
self.yaSock2 = socksocket(AF_INET, SOCK_STREAM)
self.yaSock2.settimeout(5)
self.yaSock2.setproxy(PROXY_TYPE_SOCKS5, self.proxy2[0], int(self.proxy2[1]))
self.yaSock2.connect((chatConnection[0], int(chatConnection[1])))
send(self.yaSock, "<ya r=\"%s\" u=\"%s\" c=\"%s\" k=\"%s\" />\0" % (room, self.user["UserId"][0], self.ya, self.xml["k"]))
print read(self.yaSock)
self.yaSock.close()
send(self.yaSock2, "<ya r=\"%s\" u=\"%s\" c=\"%s\" k=\"%s\" />\0" % (room, self.user2["UserId"][0], self.ya2, self.xml2["k"]))
print read(self.yaSock2)
self.yaSock2.close()
self.j2 = "<j2 Y=\"2\" l5=\"" + self.l5 + "\" l4=\"1200\" l3=\"844\" l2=\"0\" cb=\"0\" q=\"1\" y=\"" + self.xml["i"] + "\" k=\"" + self.user["k1"][0] + "\" k3=\"0\" p=\"0\" c=\"" + room + "\" f=\"2\" u=\"" + self.user["UserId"][0] + "\" d0=\"0\" n=\"Zuhnny\" a=\"1\" h=\"xat sux\" v=\"0\" />\0"
self.j22 = "<j2 Y=\"2\" l5=\"" + self.l52 + "\" l4=\"1200\" l3=\"844\" l2=\"0\" cb=\"0\" q=\"1\" y=\"" + self.xml2["i"] + "\" k=\"" + self.user2["k1"][0] + "\" k3=\"0\" p=\"0\" c=\"" + room + "\" f=\"2\" u=\"" + self.user2["UserId"][0] + "\" d0=\"0\" n=\"Zuhnny\" a=\"1\" h=\"xat sux\" v=\"0\" />\0"
send(self.socket, self.j2)
send(self.socket2, self.j22)
while True:
print self.socket.recv(6096)
print self.socket2.recv(6096)
sleep(1)
send(self.socket, "<m t=\" F U C K X A T %s\" u=\"%s\" />\0" % (randint(0,5000), self.user["UserId"][0]))
send(self.socket2, "<m t=\" F U C K X A T %s\" u=\"%s\" />\0" % (randint(0,5000), self.user2["UserId"][0]))
except IOError, err: pass
except Exception, error: pass
def read(socket):
data = socket.recv(1024)
return data
def send(socket, data):
socket.sendall(data)
def getChatConnection(room):
print '\ntest\n'
if not isfile('./_files/ips.txt') or time() - getmtime('./_files/ips.txt') > 86400:
fh = open('./_files/ips.txt', 'w')
fh.write(urlopen('http://xat.com/web_gear/chat/ip2.htm?' + str(time())).read())
fh.close()
try:
fh = open('./_files/ips.txt', 'r')
iprules = loads(fh.read())
Fx = iprules[iprules["order"][0][0]]
xAddr = Fx[1][randint(0, len(Fx[1]) - 1)].split(':')
if len(xAddr) == 1: xAddr.append(10000)
if len(xAddr) == 2: xAddr.append(39)
xPort = xAddr[1] + randint(0, xAddr[2] - 1)
return (xAddr[0], 9999 + int(room) if int(room) < 8 else 10007 + (int(room) % 32))
except Exception, e:
print e
file = open("./_files/proxies.txt")
proxyLen = len(map(lambda(x): x.split(':'), file))
file2 = open("./_files/ids.txt")
idLen = len(map(lambda(x): x.split('\n'), file2))
threadLock = Lock()
threads = []
room = raw_input("Room ID to raid: ")
chatConnection = getChatConnection(room)
for x in range(1000):
threads.append(myThread(x, "Thread-" + str(x)).start())
# Wait for all threads to complete
for t in threads:
t.join()
print "Exiting Main Thread"
I have a guess at your problem. I don't think it actually is race conditions at all. I haven't read all of your code carefully, but I don't see any global or otherwise shared variables being mutated. But I do see a different problem.
You aren't buffering up your reads; you're just expecting that each bSock.recv(1024) is going to receive exactly one message. That isn't how TCP works; you may receive half of a message, or two messages, or the second half of the previous message and the first half of the next.
If you don't stress your computer or the network very hard, and your messages are all pretty small, it may (depending on the platform) work 99.9% of the time, meaning you don't notice any problem. But as soon as you stress things, it'll start to fail more often.
And you've got 400 threads, and from your old-style code (e.g., except Type, value) it looks like you may be on a system old enough that it's stuck on Python 2.5, which means you may be stressing the system very hard.
You need to fix this by receiving in a loop until you have one or more complete messages, then handling those messages, then returning to the loop, instead of handling each recv as if it were guaranteed to be exactly one complete message.
Fortunately, you're dealing with IRC, which (assuming you're not doing any DCC, etc.) has exactly one command per line, and Python has a nice wrapper around sockets that makes them look like line-buffered files. So you can do this:
bfile = bsock.makefile()
for line in bfile:
Now you know that line is guaranteed to be a complete line, even if it had to do three reads, and buffer up most of the third read until your next time through the loop.
You're doing the same thing in at least three places, so obviously you need to fix them all. Also, you need to make sure to close the socket and the file appropriately. And you need to detect when the other sides closes the socket. (The recv, or the next line, will return an empty string.)
Another possibility:
There is at least one thing all of the threads are sharing: that bsock socket. And they all do this 5 seconds after launch:
bSock.sendall("<bot p=\"%s\" au=\"%s\" yi=\"%s\" />\0" % (xml["p"], xml["au"], xml["i"]))
data = bSock.recv(1024)
What's to stop thread #42 from doing its sendall, then thread #23 doing its sendall, then thread #42 from doing its recv and getting the data intended for thread #42?
This is what's called a "critical section" or "atomic block": a chunk of code that only one thread can run at a time or everyone will get confused. The usual way around it is to share a Lock, and have each thread acquire the Lock before running this code. If thread #42 already has the lock, and thread #23 tries to acquire it, it will be blocked until thread #42 releases the lock, so there's no chance of them conflicting. So:
bSockLock = threading.Lock()
# ...
for x in range(400):
Thread(target = __init__, args=[chatConnection, bSock, bSockLock]).start()
# ...
def __init__(chatConnection, bSock):
# ...
for x in range(3):
start(chatConnection, proxies[x][0], proxies[x][1], [ids[x]["UserId"][0], ids[x]["k1"][0], ids[x]["k2"][0]], room, bSock, bSockLock)
# ...
def start(chatConnection, proxyIP, proxyPort, user, room, bSock, bSockLock):
# ...
with bSockLock:
bSock.sendall("<bot p=\"%s\" au=\"%s\" yi=\"%s\" />\0" % (xml["p"], xml["au"], xml["i"]))
data = bSock.recv(1024)

Python weird code error

I have an IRC bot and I'm trying to get information for game server (GTA SA Multiplayer).
I have ready-to-use query, but I can't implement it into my bot. It works if I try to load the same script, but without getting it into bot's structure. The error it gives me is
NameError: name 'ip' is not defined
I've tried adding the ip address as argument in def(inp,say=None), but it still didn't work. That's the code:
from util import Query
from util import hook
import sys
#hook.command
def serverinfo(inp,ip="",port="",say=None):
ip = "78.129.221.58"
port = 7777
if len(sys.argv) >= 3:
ip = str(sys.argv[1])
port = int(sys.argv[2])
query = Query(ip,port)
info = query.GetInformation()
say(info)
if info['players'] <= 100:
say(query.GetPlayers())
say(query.GetDetailedPlayers())
else: say('can\' get players because players is above 100')
say(query.Ping())
query.Close()
That's Query that I import:
import socket, struct, random, datetime
from cStringIO import StringIO
class Query:
def __init__(self, ip, port):
self.ip, self.port = socket.gethostbyname(ip), port
self.data = StringIO("")
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.connect((ip, port))
self.sock.settimeout(1)
def CreatePacket(self, opcode):
ips = self.ip.split('.');
packet = "SAMP{0}{1}{2}{3}{4}{5}{6}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode)
if opcode == 'p':
packet += struct.pack("BBBB", random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
return packet
def GetInformation(self):
try:
self.sock.send(self.CreatePacket('i'))
info = {}
self.data = StringIO(self.sock.recv(2048))
self.data.read(11)
info['passworded'] = struct.unpack('?', self.data.read(1))[0]
info['players'] = struct.unpack('h', self.data.read(2))[0]
info['maxplayers'] = struct.unpack('h', self.data.read(2))[0]
info['hostname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
info['gamemode'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
info['mapname'] = self.data.read(struct.unpack('i', self.data.read(4))[0])
except socket.timeout:
info['error'] = 1
return info
def GetRules(self):
try:
self.sock.send(self.CreatePacket('r'))
rules = {}
self.data = StringIO(self.sock.recv(2048))
self.data.read(11)
rulecount = struct.unpack('h', self.data.read(2))[0]
for i in range(rulecount):
name = self.data.read(struct.unpack('b', self.data.read(1))[0])
rules[name] = self.data.read(struct.unpack('b', self.data.read(1))[0])
except socket.timeout:
rules['error'] = 1
return rules
def GetPlayers(self):
try:
self.sock.send(self.CreatePacket('c'))
players = []
self.data = StringIO(self.sock.recv(2048))
self.data.read(11)
playercount = struct.unpack('h', self.data.read(2))[0]
for i in range(playercount):
name = self.data.read(struct.unpack('b', self.data.read(1))[0])
players.append([name, struct.unpack('i', self.data.read(4))[0]])
except socket.timeout:
players = {'error': 1}
return players
def GetDetailedPlayers(self):
try:
self.sock.send(self.CreatePacket('d'))
players = []
self.data = StringIO(self.sock.recv(2048))
self.data.read(11)
playercount = struct.unpack('h', self.data.read(2))[0]
for i in range(playercount):
playerid = struct.unpack('b', self.data.read(1))[0]
name = self.data.read(struct.unpack('b', self.data.read(1))[0])
score = struct.unpack('i', self.data.read(4))[0]
ping = struct.unpack('i', self.data.read(4))[0]
players.append([playerid, name, score, ping])
except socket.timeout:
players = {'error': 1}
return players
def Close(self):
self.sock.close()
def Ping(self):
packet = self.CreatePacket('p')
a = datetime.datetime.now()
self.sock.send(packet)
self.sock.recv(2048)
b = datetime.datetime.now()
c = b - a
return int((c.days * 24 * 60 * 60 + c.seconds) * 1000 + c.microseconds / 1000.0)
class Rcon:
def __init__(self, ip, port, password):
self.ip, self.port, self.password = socket.gethostbyname(ip), port, password
self.data = StringIO("")
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.connect((ip, port))
self.sock.settimeout(0.5)
def CreatePacket(self, opcode, password, command):
ips = self.ip.split('.');
packet = "SAMP{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}".format(chr(int(ips[0])), chr(int(ips[1])), chr(int(ips[2])), chr(int(ips[3])), chr(self.port & 0xFF), chr(self.port >> 8 & 0xFF), opcode, chr(len(password) & 0xFF), chr(len(password) >> 8 & 0xFF), password, chr(len(command) & 0xFF), chr(len(command) >> 8 & 0xFF), command)
return packet
def Send(self, command):
self.sock.send(self.CreatePacket('x', self.password, command))
output = []
while 1:
try:
self.data = StringIO(self.sock.recv(2048))
self.data.read(11)
strlen = struct.unpack('h', self.data.read(2))[0]
if strlen == 0: break
output += [self.data.read(strlen)]
except: break;
return output
def Close(self):
self.sock.close()
Any ideas?
Edit: After some changes I did, gives me the following error:
query = Query(ip,port)
TypeError: 'module' object is not callable
I've basically changed the location of ip and port, moved it out of the serverinfo command.
from util import Query
from util import hook
ip = "78.129.221.58"
port = 7777
query = Query(ip,port)
info = query.GetInformation()
#hook.command
def serverinfo(inp,ip="",port="",say=None):
say(info)
if info['players'] <= 100:
say(query.GetPlayers())
say(query.GetDetailedPlayers())
else: say('can\' get players because players are above 100')
say(query.Ping())
query.Close()
Try adding this to the start of the python code :
ip = "78.129.221.58"
port = 7777
Try
query = Query.Query(ip, port)
The problematic line is this one:
query = Query(ip,port)
If the initialization using the command line parameters fail or if you pass in insufficient arguments, ip will not be initialized resulting in the said error.
Also, a better way of testing out scripts is something like this:
def main():
if len(sys.argv) >= 3:
ip = str(sys.argv[1])
port = int(sys.argv[2])
query = Query(ip,port)
# start using query
else:
raise Exception("Insufficient args passed in")
if __name__ == '__main__':
main()
Raising an exception/error or printing out something guarantees that you know that insufficient args are passed in. Also, maybe move all that code out in the open to some function?

Python pyserial and runaway CPU usage

MacOS 10.7.3, python 2.5
I am using pyserial to open a connection to an external server. The connection is opened as:
HOST = '10.0.0.1'
PORT = '16010'
theURL = 'socket://' + HOST + ':' + PORT
conn = serial.serial_for_url(theURL, baudrate=115200)
conn.timeout = 2
and then the read looks like this:
try:
while len(rawData) == 0 and self.shutdown == False:
rawData = conn.readline()
except:
some error handling code...
The problem is, if I kill the server at 10.0.0.1:16010 the code keeps running, but the cpu usage goes to 100%. No error is thrown, so the except is never entered.
This looks like a problem in pyserial, but maybe someone here has run into this before and knows how to detect the lost connection so the situation can be handled gracefully.
Thanks.
If you're not depending on .readline() you could do it like this:
self.plugin.conn = Serial(..., timeout = 1)
...
if not self.shutdown:
rawData = self.plugin.conn.read(1)
if rawData:
rawData += self.plugin.conn.read(self.plugin.conn.inWaiting())
else:
raise Exception("timeout")
I'm not sure if I got your intent right so you might have to adjust...
The fact that your CPU usage is pegged probably indicates the the readline call is not blocking to timeout but returns instantly. So if your normal timeout
is 2, you could use:
from time import time
try:
while len(rawData) == 0 and self.shutdown == False:
before = time()
rawData = conn.readline()
if (len(rawData)==0) and ((time()-before)<2):
raise Exception("Early readline return.")
except:
some error handling code...
A very good solution to this can be found here:
class ReadLine:
def __init__(self, s):
self.buf = bytearray()
self.s = s
def readline(self):
i = self.buf.find(b"\n")
if i >= 0:
r = self.buf[:i+1]
self.buf = self.buf[i+1:]
return r
while True:
i = max(1, min(2048, self.s.in_waiting))
data = self.s.read(i)
i = data.find(b"\n")
if i >= 0:
r = self.buf + data[:i+1]
self.buf[0:] = data[i+1:]
return r
else:
self.buf.extend(data)
ser = serial.Serial('COM7', 9600)
rl = ReadLine(ser)
while True:
print(rl.readline())

What's wrong with my simple HTTP socket based proxy script?

I wrote a simple Python script for a proxy functionality. It works fine, however, if the requested webpage has many other HTTP requests, e.g. Google maps, the page is rendered quite slow.
Any hints as to what might be the bottleneck in my code, and how I can improve?
#!/usr/bin/python
import socket,select,re
from threading import Thread
class ProxyServer():
def __init__(self, host, port):
self.host=host
self.port=port
self.sk1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def startServer(self):
self.sk1.bind((self.host,self.port))
self.sk1.listen(256)
print "proxy is ready for connections..."
while(1):
conn,clientAddr = self.sk1.accept()
# print "new request coming in from " + str(clientAddr)
handler = RequestHandler(conn)
handler.start()
class RequestHandler(Thread):
def __init__(self, sk1):
Thread.__init__(self)
self.clientSK = sk1
self.buffer = ''
self.header = {}
def run(self):
sk1 = self.clientSK
sk2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while 1:
self.buffer += sk1.recv(8192)
if self.buffer.find('\n') != -1:
break;
self.header = self.processHeader(self.buffer)
if len(self.header)>0: #header got processed
hostString = self.header['Host']
host=port=''
if hostString.__contains__(':'): # with port number
host,port = hostString.split(':')
else:
host,port = hostString,"80"
sk2.connect((host,int(port)))
else:
sk1.send('bad request')
sk1.close();
return
inputs=[sk1,sk2]
sk2.send(self.buffer)
#counter
count = 0
while 1:
count+=1
rl, wl, xl = select.select(inputs, [], [], 3)
if xl:
break
if rl:
for x in rl:
data = x.recv(8192)
if x is sk1:
output = sk2
else:
output = sk1
if data:
output.send(data)
count = 0
if count == 20:
break
sk1.close()
sk2.close()
def processHeader(self,header):
header = header.replace("\r\n","\n")
lines = header.split('\n')
result = {}
uLine = lines[0] # url line
if len(uLine) == 0: return result # if url line empty return empty dict
vl = uLine.split(' ')
result['method'] = vl[0]
result['url'] = vl[1]
result['protocol'] = vl[2]
for line in lines[1: - 1]:
if len(line)>3: # if line is not empty
exp = re.compile(': ')
nvp = exp.split(line, 1)
if(len(nvp)>1):
result[nvp[0]] = nvp[1]
return result
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8088
proxy = ProxyServer(HOST,PORT)
proxy.startServer()
I'm not sure what your speed problems are, but here are some other nits I found to pick:
result['protocal'] = vl[2]
should be
result['protocol'] = vl[2]
This code is indented one level too deep:
sk2.connect((host,int(port)))
You can use this decorator to profile your individual methods by line.

Categories

Resources