PostHeaderIcon P2P Drawing and Chat Program in Python

Network Programming in Python and Graphics

In this Tutorial I will try and explain simple Networking concepts in Python. Some things you will learn here are GUI programming, Networking, threading and hopefully enough understanding to be able to send binary data over the network.

from Tkinter import *
import socket
from threading import *
import cPickle

Our import statements you will notice we import our GUI modules, our socket modules, threading for keeping the GUI from freezing during connections. Finally cPickle his allows to send binary data over the network

CMD_MSG, CMD_LINE = range(2)

create some global variables

first we define our server function assign a port to listen to and bind it to our IP address


def server():
port = 9000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((socket.gethostbyname(socket.gethostname()), int(port))) # bind to ip

next we create our loop

while True:
msg, addr = s.recvfrom(2024)
cmd, msg = ord(msg[0]),msg[1:]
and listen for any data coming through

if cmd == CMD_LINE: #DRAW A LINE
dx,dy,ex,ey=cPickle.loads(msg)
canvas.create_line(dx,dy,ex,ey,width=2, fill=”red”)
elif cmd == CMD_MSG:
listb1.insert(END, str(msg) + “\n”)

if our data is equal to one of our global variables draw or write a message depending on what it equals (You will see soon how we send that data from our client so that the server knows what to interpret)

def client(msg):
port = 9000
host = str(entryhost.get())
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(str(username.get)+” : ” + msg, (host, int(port)))

this is our messaging function

what it does:

connects to port 9000 on the host (remote computer) and sends a message which we will craft later

These are our drawing functions for drawing lines on a canvas

def move(e):
global lastLine,mx,my
canvas.delete(lastLine)
mx, my = e.x, e.y

# draw a new temp line
lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill=’Black’)

def bdown(e):
global lastLine,dx,dy,mx,my
canvas.bind(”, move) #start receiving move msgs
dx,dy=e.x,e.y
mx,my=e.x,e.y

# draw a temp line
lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill=’Black’)
and here is the actual data were sending

def bup(e):
#canvas.delete(lastLine)
canvas.unbind(”)

#send out the draw-a-line command
client(chr(CMD_LINE)+cPickle.dumps((dx,dy,e.x,e.y),1))
you will notice we are calling our client command and you remember our global variables. So when we call our client function with the global variable our server recognizes it and does what it needs to do


def sendit(foo):
client(chr(CMD_MSG) + str(textboxsend.get()))
listb1.insert(1.0, str(textboxsend.get()) + "\n")
textboxsend.delete(0, END)

same with our messaging function

Some GUI code

root = Tk()
root.title(“Simple P2P Chat App”)
root.wm_resizable(0, 0)
root.minsize(550, 400)
#root.wm_iconbitmap(“shinobi.ico”)
#root.option_readfile(“optionDB”)

our threading code “simple eh”

mythread = Thread(target=server)
mythread.start()

Now for more GUI code

frame = Frame(root)
entryhost = Entry(frame)
entryhost.pack(side=LEFT, fill=X, expand=True)
entryhost.insert(0, “127.0.0.1″)
label = Label(frame, text=”Enter IP or Domain”)
label.pack(side=LEFT)
username = Entry(frame)
username.pack(side=LEFT, fill=X, expand=True)

label = Label(frame, text=”Enter Your Username”)
label.pack(side=LEFT)
frame.pack(fill=X)

frame2 = Frame(root)

scrollbar2 = scrollbar2 = Scrollbar(frame2)
scrollbar2.pack(side=LEFT, fill=Y)
listb1 = Text(frame2)
listb1.pack(side=LEFT, fill=BOTH, expand=True)
scrollbar2.config(command=listb1.yview)
listb1.config(yscrollcommand=scrollbar2.set)

canvas = Canvas(frame2, background=”white”, width=200, height=400)
canvas.pack(side=LEFT)
canvas.bind(”,bdown)
canvas.bind(”, bup)

frame2.pack(fill=BOTH, expand=True)

frame.pack(fill=BOTH, expand=True)

frame = Frame(root)
textboxsend = Entry(frame)
textboxsend.pack(side=LEFT, fill=X, expand=True)
textboxsend.bind(”,sendit)
textboxsend.focus_set()
label = Label(frame, text=”Enter Your Message and Press Enter”)
label.pack(side=LEFT)
frame.pack(fill=X)

root.mainloop()

and were done

here is the complete source

### P2P Chat Draw with white board by Andrew Evans aka Maboroshi

from Tkinter import *
import socket
from threading import *
import cPickle
CMD_MSG, CMD_LINE = range(2)

def server():
port = 9000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((socket.gethostbyname(socket.gethostname()), int(port)))
#print socket.gethostbyname(socket.gethostname())
while True:
msg, addr = s.recvfrom(2024)
cmd, msg = ord(msg[0]),msg[1:]
if cmd == CMD_LINE: #DRAW A LINE
dx,dy,ex,ey=cPickle.loads(msg)
canvas.create_line(dx,dy,ex,ey,width=2, fill=”red”)
elif cmd == CMD_MSG:
listb1.insert(END, str(msg) + “\n”)

def saveit():
try:
output1 = listb1.get(1.0, END)
str(output1)
try:
filename = tkFileDialog.asksaveasfilename()
except:
pass
entry2.insert(END, filename)
fileit = open(filename, “w”)
fileit.write(output1)
except:
listb1.insert(END, “Failed Saving Data\n”)

def client(msg):
port = 9000
host = str(entryhost.get())
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(str(username.get)+” : ” + msg, (host, int(port)))

def move(e):
global lastLine,mx,my
canvas.delete(lastLine)
mx, my = e.x, e.y

# draw a new temp line
lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill=’Black’)

def bdown(e):
global lastLine,dx,dy,mx,my
canvas.bind(”, move) #start receiving move msgs
dx,dy=e.x,e.y
mx,my=e.x,e.y

# draw a temp line
lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill=’Black’)

def bup(e):
#canvas.delete(lastLine)
canvas.unbind(”)

#send out the draw-a-line command
client(chr(CMD_LINE)+cPickle.dumps((dx,dy,e.x,e.y),1))

def sendit(foo):
client(chr(CMD_MSG) + str(textboxsend.get()))
listb1.insert(1.0, str(textboxsend.get()) + “\n”)
textboxsend.delete(0, END)

root = Tk()
root.title(“Simple P2P Chat App”)
root.wm_resizable(0, 0)
root.minsize(550, 400)
#root.wm_iconbitmap(“shinobi.ico”)
#root.option_readfile(“optionDB”)

mythread = Thread(target=server)
mythread.start()

frame = Frame(root)
entryhost = Entry(frame)
entryhost.pack(side=LEFT, fill=X, expand=True)
entryhost.insert(0, “127.0.0.1″)
label = Label(frame, text=”Enter IP or Domain”)
label.pack(side=LEFT)
username = Entry(frame)
username.pack(side=LEFT, fill=X, expand=True)

label = Label(frame, text=”Enter Your Username”)
label.pack(side=LEFT)
frame.pack(fill=X)

frame2 = Frame(root)

scrollbar2 = scrollbar2 = Scrollbar(frame2)
scrollbar2.pack(side=LEFT, fill=Y)
listb1 = Text(frame2)
listb1.pack(side=LEFT, fill=BOTH, expand=True)
scrollbar2.config(command=listb1.yview)
listb1.config(yscrollcommand=scrollbar2.set)

canvas = Canvas(frame2, background=”white”, width=200, height=400)
canvas.pack(side=LEFT)
canvas.bind(”,bdown)
canvas.bind(”, bup)

frame2.pack(fill=BOTH, expand=True)

frame.pack(fill=BOTH, expand=True)

frame = Frame(root)
textboxsend = Entry(frame)
textboxsend.pack(side=LEFT, fill=X, expand=True)
textboxsend.bind(”,sendit)
textboxsend.focus_set()
label = Label(frame, text=”Enter Your Message and Press Enter”)
label.pack(side=LEFT)
frame.pack(fill=X)

root.mainloop()

Leave a Reply

Search
Awesome Links
Subscribe
Vote for Flyninja
Random Reading