Follow us on Twitter!
Hacking isn't just Computers & Exploits. It's a Philosophy. - Mr_Cheese
Friday, April 18, 2014
Navigation
Home
HellBoundHackers Main:
HellBoundHackers Find:
HellBoundHackers Information:
Learn
Communicate
Submit
Shop
Challenges
HellBoundHackers Exploit:
HellBoundHackers Programming:
HellBoundHackers Think:
HellBoundHackers Track:
HellBoundHackers Patch:
HellBoundHackers Other:
HellBoundHackers Need Help?
Other
Members Online
Total Online: 18
Guests Online: 18
Members Online: 0

Registered Members: 82822
Newest Member: TheBunter
Latest Articles

Threading and Sockets in Python

Arrow Image An article about two of the hardest and most misunderstood parts of programming, in which I walkthrough writing a P2P chat program



First off, all code within this article is my own work, and while I encourage you to use this program and it\'s parts, if you use big chunks, please credit me.
Also, because HBH has no TAB support (ugh) i\'ve just left this unformatted. for functional code go to the URL at the bottom.


I\'m assuming that you have a moderate background in python.

Now, sockets and threading, two things that are a genuine pain in the arse, until you get to know them.
A brief overview:

SOCKETS:

These are the primary way that data is transmitted over an IP connection.
You create an open socket on one machine, which opens a port (always use at least 5 digits to avoid overlap), and can then be connected to by another machine.
From here data sent by the machine that connects is buffered and recieved by the machine withg the open socket.
You can have 1 connection per port, remember that the port of the connecting socket must match the recieving one.

THREADING:

Threading is a way of having a computer do more than one thing at once.
It allows you to set a task running, and then have the computer go off and do something else while still performing the first task.
Used in games, to facilitate AI, and look for input from player among many other things.
In a low level language like C++ it can often be just as efficient to write a well constructed sequence of checks, rather than threads, but in an interpreted language like python the change is speed is generally quite dramatic.


Now onto the Python side of things.

First sockets.
#begin sample socket client code (this is the bit to send messages)


import socket #needed to use sockets
from socket import * # we need everything
class SockClient(object): #we\'re making a class for our client
def __init__(self, host, port): #the __init__() method is run whenever a class is called
self.host = host #making the inputs native to the class, so we can use them repeatedly.
self.port = port #for this example it\'s not actually necessary, but a good habit to get into
self.addr = (self.host, self.port)

sock = None
for res in getaddrinfo(self.host, self.port, AF_UNSPEC, SOCK_STREAM): #this outputs a list with the details about the coket type we\'ll be using. just trust me here, to go into more detail is way beyond the scope of this article
af, socktype, proto, canonname, sa = res #using the for loop is the easiest way to extract the data from the list
try:
sock = socket(af, socktype, proto) #creating a socket, passing on the data we just collected
except error, msg: #error handling, means we get a nice(ish) message if something goes wrong
sock = None
continue
try:
sock.connect(sa) #try to connect to our server, sa is a tuple with our reformatted host and port data
except error, msg: #more error handling
sock.close()
sock = None
continue
break
if sock is None:
raise RuntimeError, \"could not connect socket\"

self.sock = sock #finally makes the socket callable
def remotemsg(self,msg): # this function sends a message, and takes one input
self.sock.send(msg)
del msg
def close(self): # a funtion to cleanly kill the socket
self.sock.shutdown(SHUT_RDWR)
self.sock.close()

if you followed this right, and run it in a terminal, you now have a chat client. but wait nothing to connect to....


so

#begin sample socket server code


import socket
from socket import *

class SockServer(object):
def __init__(self, port):
self.port = port #again, we define a class, and make all the inputs local to it
self.host = \'\'
self.addr = (self.host, self.port)
self.buf = 1024 # this variable will tell it how many characters to go looking for when it finds a message

sock = None
for res in getaddrinfo(self.host, self.port, AF_UNSPEC, SOCK_STREAM, 0, AI_PASSIVE): #again, we get the addressinfo, but the 0 and AI_passive tags tell it that this will be recieving, not sending
af, socktype, proto, canonname, sa = res
try:
sock = socket(af, socktype, proto)
except error, msg:
sock = None #again, error handling
continue
try:
sock.bind(sa) # here it is binding it to a local port, so that it can listen to the outside world
sock.listen(1) # listening for connection
except error, msg:
sock.close()
sock = None
continue
break
if sock is None:
raise RuntimeError, \"could not open socket\"

self.sock,addr = sock.accept() #accept the first connection it finds
self.mainloop()
def mainloop(self):
while 1: #endless while loop
data = self.sock.recv(self.buf) #see if the other user has sent us anything
if not data: # if data is empty, they\'ve left, so we should too
print \"Remote user has terminated the session.\"
break
else:
print \'remote_user:\',data #otherwise, show us what they wrote!
print \"message?:\"
del data
self.close()
def close(self):
self.sock.shutdown(SHUT_RDWR) #again, a clean kill
self.sock.close()


so now if we run these on diffent machines, and open the server first, then the client, we can send messages one way.

but we want to chat, which means we need threading.

threading incorporates the threading module, and jsut means that the thread will do what it\'s doing in the background.
to illustrate this i\'ll write a thread that adds a number to a variable \'a\' whenever \'a\' has a value
#begin threading example
import threading #so we can use threads

class OurThread(threading.Thread): #this isn\'t an object, it\'s a thread so we tell it
def __init__(self, factor): # we want to take input, so we re-write the threading __init__() function
self.factor = factor #make it local
threading.Thread.__init__(self) #we still need the threading __init__() function
def run(self):
global a #tell it to look for any instance of a variable a
while 1:
if a != None:
a +=self.factor # if a exists add 2, print it, and then make it None again
print a
a = None


now if we execute OurThread(2).start()
and then type a=2
it will print 4
this is very handy, and a very simple example, but will tell you enough to play around.

now a full blown example:


import threading
import socket #import the stuff we need
from socket import *


class SockClient(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.addr = (self.host, self.port)

sock = None
for res in getaddrinfo(self.host, self.port, AF_UNSPEC, SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
sock = socket(af, socktype, proto)
except error, msg:
sock = None
continue
try:
sock.connect(sa) #the same as our old client
except error, msg:
sock.close()
sock = None
continue
break
if sock is None:
raise RuntimeError, \"could not connect socket\"

self.sock = sock
def remotemsg(self,msg):
self.sock.send(msg)
del msg
def close(self):
self.sock.shutdown(SHUT_RDWR)
self.sock.close()


class SockServer(threading.Thread):
def __init__(self, port):
self.port = port
threading.Thread.__init__(self)
def run(self):
self.host = \'\'
self.addr = (self.host, self.port)
self.buf = 1024

sock = None
for res in getaddrinfo(self.host, self.port, AF_UNSPEC, SOCK_STREAM, 0, AI_PASSIVE):
af, socktype, proto, canonname, sa = res
try:
sock = socket(af, socktype, proto)
except error, msg:
sock = None
continue
try:
sock.bind(sa) #the same as our old server, but implemented as a thread
sock.listen(1)
except error, msg:
sock.close()
sock = None
continue
break
if sock is None:
raise RuntimeError, \"could not open socket\"

self.sock,addr = sock.accept()
self.mainloop()
def mainloop(self):
while 1:
data = self.sock.recv(self.buf)
if not data:
print \"Remote user has terminated the session.\"
break
else:
print \'remote_user:\',data
print \"message?:\"
del data
self.close()
def close(self):
self.sock.shutdown(SHUT_RDWR)
self.sock.close()

send_ip = raw_input(\'What is other ip?\')
send_port = input(\'What is other port?\')
open_port = input(\'What is your open port?\') #finally a system for managing input and output
SockServer(open_port).start()
fake = raw_input(\'Press return when you both have this message.\')
insock = SockClient(send_ip, send_port)
while 1:
print \'Message?:\'
msg = raw_input()
if msg:
insock.remotemsg(msg)




try this code, it works well.
I\'ve uploaded this article at
www.freewebs.com/richohealey/python/threadart.txt
and just the code segments at
www.freewebs.com/richohealey/python/threadcode.txt
you just have to chop it up into the indivdual programs and save as **something**.py
the uncommented funtional chat code is at
www.freewebs.com/richohealey/python/chat.py

thanks for reading.


-RichoHealey

Comments

cubeman372on October 04 2006 - 19:40:05
Grin you sure know you're Python
richohealeyon October 05 2006 - 00:29:29
yeah. good language. i realise that this is pretty advanced, but i figure sooner or later someone wil benifit.
Greekilon October 07 2006 - 03:02:31
Wow... I'm actually working on something just like this at the moment (although much more simple)... Thanks alot, this will be a really helpful guideline.
netfishon January 29 2007 - 15:19:39
truly the "Python God" ... well done, dude.
Post Comment

Sorry.

You must have completed the challenge Basic 1 and have 100 points or more, to be able to post.