writing text area in python, implementing sockets
Question: I am doing a simulation of a print server in python, files are sent using
sockets to a server which has to be placed in a printer queue. When the client
initiates communication with the server must provide an ID (user) and
PASSWORD, which will be checked against a list on the server can be verified
in a file "passwordlist.txt" which has the following format:

    
    
    akira Aaron
    alazrea Ababa
    alexander Abbott
    andy Abe
    andycapp Abel
    anxieties Abelian
    anxiety Abelson
    bailey Aberdeen
    batman robin
    bd Abidjan
    

Both programs must have a graphical interface on the display: * Client: user
field, password, file to send to print and disconnect from the server. *
Server: A list of files that are queued for printing On the server should be
displayed a list of files that have been properly sent to the queue for
printing.

For this I decided to use a "text area" but I have a problem, only shows me
the first file in the command to print text area, when the client terminates
the connection and if another client tries to connect to the server just crash
the program does and does absolutely nothing. What am I doing wrong? I think
the problem is that i'm putting part of the instruction code "root.mainloop
()", i have this doubt. how can resolve this failure? im stuck With
This..thanks to all

Here's the Client Code:

    
    
    #! /python26/python.exe
    #! -*- coding: utf-8 -*-
    
    from Tkinter import * 
    import Tkinter, Tkconstants, tkFileDialog
    import Tkinter
    import sys
    import socket
    import tkMessageBox
    
    flag = False
    class Exit_Button(Frame):
        def __init__(self, parent=None):
            Frame.__init__(self, parent)
            self.pack()
            self.widget1()
    
    def salir():
        root.destroy()
    
    def adjuntar_imprimir():
        global flag
        if (flag==False):
            tkMessageBox.showinfo("Error", "You must login") 
            salir ()
        else:
        # get filename
    
            filename = tkFileDialog.askopenfilename(**file_opt)
        # open file on your own
            if filename:
                s.send (filename)
                f= open(filename, 'rb')
                l = f.read(1024)
                while (l):
                    s.send(l)
                    l = f.read(512)
    
    
    
    def iniciar_sesion():
        global flag
        #invoco  el metodo connect del socket pasando como parametro la tupla IP , puerto 
        login = value.get()
        password = value_2.get()
        if ((len(login) == 0) or (len(password)) == 0):
            tkMessageBox.showinfo("Error", "insert correct login and password") 
            salir ()
        else:
            s.send(login)
            s.send(password)
            recibido = s.recv(1024)
            tkMessageBox.showinfo("Notify", recibido)
            if (recibido=="Error Check user & Password"):
                salir ()
            else:
                flag = True
    
    ##@@--------------------------------------------------------------------------------@@##    
    
    root = Tk() 
    s = socket.socket()
    s.connect(("localhost",  9999))  
    # define options for opening or saving a file
    file_opt = options = {}
    options['defaultextension'] = '' # couldn't figure out how this works
    options['filetypes'] = [('all files', '.*'), ('text files', '.txt')]
    options['initialdir'] = 'C:\\'
    options['initialfile'] = 'myfile.txt'
    options['parent'] = root
    options['title'] = 'This is a title'
    
    
    frame = Frame(root) 
    frame.pack(side=LEFT) 
    frame.master.title("Servicio de impresion")
    value = StringVar()
    value_2 = StringVar()
    
    w =  Label(root, text="User Name", fg="red")
    w.pack(side = LEFT)
    entry_1 = Entry(root, textvariable=value_2, bd =5, show="*")
    entry_1.pack(side = RIGHT)
    
    
    z=  Label(root, text="Password", fg="red")
    z.pack(side = RIGHT)
    entry_0 = Entry(root, textvariable=value, bd =5)
    entry_0.pack(side = RIGHT)
    
    ##---------------login----------------
    button_0= Button (frame,  text = "login",  command= iniciar_sesion, bg='black', foreground ="red") 
    button_0.pack()
    
    ##--------------Attach and print File------------
    button_3 = Button (frame, text= "print", command=adjuntar_imprimir, bg='black',foreground ="red")
    button_3.pack(side=LEFT)
    
    
    ##-----------------Exit------------------------
    button_1 = Button(frame, text= "exit", command=salir, bg='black', foreground ="red") 
    button_1.pack()
    
    root.mainloop() 
    

The Server Code:

    
    
    from Tkinter import * 
    import Tkinter, Tkconstants, tkFileDialog
    import Tkinter
    import sys
    import socket
    import tkMessageBox
    def onclick():
       pass
    
    root = Tk()
    root.title("Print Server")
    text = Text(root, width=60, height=30)
    text.pack()
    
    s = socket.socket()
    
    s.bind(("localhost",  9999))
    s.listen(100)
    i=0
    
    while (True):
    
        sc, address = s.accept()
        print "Connection from: ", address
        recibido1 = sc.recv(1024)
        recibido2 = sc.recv(1024)
        print  "login:", recibido1, "password:",  recibido2
        salida = (str(recibido1)+" "+str(recibido2)+"\n")
        archivo = open("passwordlist.txt", "r") 
        while True:
            linea = archivo.readline()  #Leo del archivo
            if (salida==linea):
                log_ok ="login ok"
                sc.send(log_ok)      
                break
            if (len(linea))==0:
                error= "Error Check user & Password"
                sc.send(error)
                break
        f = open('print_'+ str(i)+".pdf",'wb') #abierto en escritura binaria
        i=i+1   
    # recibimos y escribimos en el fichero
        nombre_archivo = sc.recv(1024)
        cadena = "On Impresion Queue.."+nombre_archivo+"\n"
        text.insert(INSERT, cadena)
        print "On impresion Queue.."+nombre_archivo
        l = sc.recv(1024)
        while (l):
            f.write(l)
            l = sc.recv(1024)
            if not l: 
                notification= "Complete transfer"
                sc.send(notification)
                break
        f.close() 
        sc.close()
        root.mainloop()
    s.close()
    

The program does not tell me any error just when another client tries to
login, the client interface is doing nothing.


Answer: I don't know why it crashes, but I know why only one client can connect. Your
server just isn't designed to handle multiple clients. When one client
connects, all the server does is listen to that client - any other client
trying to connect is simply ignored.

The solution is simple: Multithreading. Spawn a new thread for each connecting
client, and let the "main" thread accept new connections.

The resulting "while(True)" loop should look somewhat like this:

    
    
    from threading import Thread
    tkinterThread= Thread(target=Tk.mainloop, args=[root])#spawn a new Thread object
    tkinterThread.start()#make the thread execute the tkinter mainloop
    #please note: I'm not sure if the two lines above actually work; I can't test them because Tkinter won't work for me.
    
    def listenToClient(sc, address):
        recibido1 = sc.recv(1024)
        recibido2 = sc.recv(1024)
        print  "login:", recibido1, "password:",  recibido2
        salida = (str(recibido1)+" "+str(recibido2)+"\n")
        archivo = open("passwordlist.txt", "r") 
        while True:
            linea = archivo.readline()  #Leo del archivo
            if (salida==linea):
                log_ok ="login ok"
                sc.send(log_ok)      
                break
            if (len(linea))==0:
                error= "Error Check user & Password"
                sc.send(error)
                break
        f = open('print_'+ str(i)+".pdf",'wb') #abierto en escritura binaria
        i=i+1   
    # recibimos y escribimos en el fichero
        nombre_archivo = sc.recv(1024)
        cadena = "On Impresion Queue.."+nombre_archivo+"\n"
        text.insert(INSERT, cadena)
        print "On impresion Queue.."+nombre_archivo
        l = sc.recv(1024)
        while (l):
            f.write(l)
            l = sc.recv(1024)
            if not l: 
                notification= "Complete transfer"
                sc.send(notification)
                break
        f.close() 
        sc.close()
    
    while (True):
        sc, address = s.accept()
        print "Connection from: ", address
        clientThread= Thread(target=listenToClient, args=[sc,address])#spawn a new thread object
        clientThread.start()#start the thread; it'll execute the "listenToClient" function, passing it "sc" and "address" as arguments
    

This code will (well, should) spawn a thread that takes care of the GUI,
meanwhile it'll accept connection requests from clients and spawn a new thread
for every client, which checks the client's username and password, and then
keeps listening until the client disconnects.

