#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2005
    Posts
    12
    Rep Power
    0

    MultiChat Program


    Hi,
    I have a MultiChat Program below.This Program works fine onlywithin LAN but doesn't work over it.Can anyone help me in fixing this out

    Code:
    #!/usr/bin/python
    
    from Tkinter import *
    from socket import *
    import cPickle, threading,sys,os
    
    # Each message is a command + data
    CMD_JOINED,CMD_LEFT,CMD_MSG,CMD_LINE,CMD_JOINRESP = range(5)
    people = {} # key = (ipaddr,port), value = (name,color)
    
    def sendMsg(msg):
        sendSock.send(msg,0)
    
    def onQuit():
        'User clicked Quit button'
        sendMsg(chr(CMD_LEFT)) # Notify others that I'm leaving
        root.quit()
    
    def onMove(e):
        'Called when LButton is down and mouse moves'
        global lastLine,mx,my
        canvas.delete(lastLine) # Erase temp line
        mx,my = e.x,e.y
    
        # Draw a new temp line    
        lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill='Black')
    
    def onBDown(e):
        'User pressed left mouse button'
        global lastLine,dx,dy,mx,my
        canvas.bind('<Motion>',onMove) # Start receiving move msgs
        dx,dy = e.x,e.y
        mx,my = e.x,e.y
    
        # Draw a temporary line    
        lastLine = canvas.create_line(dx,dy,mx,my,width=2,fill='Black')
    
    def onBUp(e):
        'User released left mouse button'
        canvas.delete(lastLine) # Erase the temporary line
        canvas.unbind('<Motion>') # No more move msgs, please!
    
        # Send out the draw-a-line command    
        sendMsg(chr(CMD_LINE)+cPickle.dumps((dx,dy,e.x,e.y),1))
    
    def onEnter(foo):
        'User hit the [Enter] key'
        sendMsg(chr(CMD_MSG)+entry.get())
        entry.delete(0,END) # Clear the entry widget
        
    def setup(root):
        'Creates the user interface'
        global msgs,entry,canvas
    
        # The big window holding everybody's messages    
        msgs = Text(root,width=60,height=20)
        msgs.grid(row=0,column=0,columnspan=2)
    
        # Hook up a scrollbar to see old messages
        s = Scrollbar(root,orient=VERTICAL)
        s.config(command=msgs.yview)
        msgs.config(yscrollcommand=s.set)
        s.grid(row=0,column=3,sticky=N+S)
    
        # Where you type your message    
        entry = Entry(root)
        
    
        entry.grid(row=1,column=0,columnspan=2,sticky=W+E)
        entry.bind('<Return>',onEnter)
        entry.focus_set()
    
        b = Button(root,text='Quit',command=onQuit)
        b.grid(row=1,column=2)
    
        # A place to draw
        canvas = Canvas(root,bg='White')
        canvas.grid(row=0,column=5)
        # Notify me of button press and release messages 
        canvas.bind('<ButtonPress-1>',onBDown)     
        canvas.bind('<ButtonRelease-1>',onBUp) 
    
    def msgThread(addr,port,name):
        'Listens for and processes messages'
    
        # Create a listen socket    
        s = socket(AF_INET, SOCK_DGRAM)
        s.setsockopt(IPPROTO_IP,SO_REUSEADDR,1)
        s.bind(('',port))
    
        # Join the multicast group    
        s.setsockopt(SOL_IP,IP_ADD_MEMBERSHIP, inet_aton(addr)+inet_aton(''))
        
        while 1:
            # Get a msg and strip off the command byte
            msg,msgFrom = s.recvfrom(2048)
            cmd,msg = ord(msg[0]),msg[1:]
    
            if cmd == CMD_JOINED: # New join
                msgs.insert(END,'(%s joined the chat)\n' % msg)
    
                # Introduce myself            
                sendMsg(chr(CMD_JOINRESP) + cPickle.dumps((name,myColor),1))
                
            elif cmd == CMD_LEFT: # Somebody left
                who = people[msgFrom][0]
                if who == name: # Hey, _I_ left, better quit
                    break
                msgs.insert(END,'(%s left the chat)\n' % who,'color_'+who)
                
            elif cmd == CMD_MSG: # New message to display
                who = people[msgFrom][0]
                msgs.insert(END,who,'color_%s' % who)
                msgs.insert(END,': %s\n' % msg)
                
            elif cmd == CMD_LINE: # Draw a line
                dx,dy,ex,ey = cPickle.loads(msg)
                canvas.create_line(dx,dy,ex,ey,width=2, fill=people[msgFrom][1])
                
            elif cmd == CMD_JOINRESP: # Introducing themselves
                people[msgFrom] = cPickle.loads(msg)
                who,color = people[msgFrom]
    
                # Create a tag to draw text in their color            
                msgs.tag_configure('color_' + who,foreground=color)
    
        # Leave the multicast group            
        s.setsockopt(SOL_IP,IP_DROP_MEMBERSHIP, inet_aton(addr)+inet_aton(''))
            
    if __name__ == '__main__':
        #argv = sys.argv
        #print sys.argv
        #if len(argv) < 3:
            #print 'Usage:',argv[0],'<name> <color> [addr=<multicast address>] [port=<port>]'
            #sys.exit(2)
    
        global name, addr, port, myColor
        addr = '225.0.0.37'       # Default IP address
        port = 12345        # Default port
        name= raw_input("enter ur login name : ")
        myColor='green'
        #name,myColor = argv[1:3]
        #for arg in argv[3:]:
            #if arg.startswith('addr='):
                #addr = arg[len('addr='):]
            #elif arg.startswith('port='):
                #port = int(arg[len('port='):])
    
        # Start up a thread to process messages            
        threading.Thread(target=msgThread, args=(addr,port,name)).start()
    
        # This is the socket over which we send out messages    
        global sendSock
        sendSock = socket(AF_INET,SOCK_DGRAM)
        sendSock.setsockopt(IPPROTO_IP,SO_REUSEADDR,1)
        sendSock.connect((addr,port))
    
        # Don't let the packets die too soon    
        sendSock.setsockopt(SOL_IP,IP_MULTICAST_TTL,2)
    
        # Create a Tk window and create the GUI
        root = Tk()
        root.title('%s chatting on channel %s:%s' %(addr,port,name))
        setup(root)
    
        # Join the chat!
        sendMsg(chr(CMD_JOINED)+ name)
        root.mainloop()
    Last edited by netytan; February 14th, 2005 at 05:51 AM. Reason: Added CODE tags.
  2. #2
  3. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Hey Sun,

    Please read the sticky thread at the top of this forum regarding how to ask a question. I mention this because of the lack of formatting/indentation in the code above .

    Take care,

    Mark.
    programming language development: www.netytan.com Hula

  4. #3
  5. Mini me.
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Location
    Cambridge, UK
    Posts
    783
    Rep Power
    14
    The following explains the problem but does not solve it!

    LAN based computers connect to the Internet through a gateway/firewall computer/box somewhere on the LAN. LAN based computers have private LAN IPs, the Gateway computer has two IPs (a private LAN IP and a public Internet IP). Only the public IP address is visible on the Internet.

    Client Server Programs.
    People usually have issues here when the firewall blocks access to the internat on specific ports. You might have better luck if the server is using a common port like 80.

    Peer to Peer Programs..

    Imagine a network called "WorkLAN" with computer on it called "WorkPC". WorkPC is configured to access the Internet via "WorkFirewall". This is great when it is WorkPC that acts as a client to a server (web-browsing, email, ftp download etc.). In this situation WorkPC connects to the public IP addresses of the servers.

    If the server (say a web-server) that WorkPC wants to connect to is actually behind a firewall then the firewall of the remote network needs to know what to do when a request is made by WorkPC to connect to the web server. In this situation the firewall is configured to route all web requests (port 80) a computer somewhere on its private network.

    If your chat program is both a client and a server.....
    When a remote chat program tries to connect to WorkPC it has a problem - it does not know what WorkPCs private LAN address is - so it can only use the public WorkFirewall IP address. Now, WorkFirewall does not know where to send packets from the Internet unless it has been configured. So if your chat program uses port 12345 then WorkFirewall must be configured so that any request on port 12345 are sent to WorkPC. The same must be done at the other end for the remote chat program.

    This is a problem generally for peer-to-peer programs behind firewalls.

    grim
    Last edited by Grim Archon; February 14th, 2005 at 06:32 AM.

IMN logo majestic logo threadwatch logo seochat tools logo