2012-02-21 49 views
0

我正在模擬python中的打印服務器,使用套接字將文件發送到必須放置在打印機隊列中的服務器。當客戶端啓動與服務器的通信時,必須提供一個ID(用戶)和PASSWORD,它將根據服務器上的列表進行檢查,可以在具有以下格式的文件「passwordlist.txt」中進行驗證:在python中編寫文本區域,實現套接字

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

這兩個程序都必須在顯示屏上有一個圖形界面: *客戶端:用戶字段,密碼,文件發送打印和從服務器斷開連接。 *服務器:排隊等待打印的文件列表 在服務器上應顯示已正確發送到隊列進行打印的文件列表。

爲此,我決定使用「文本區域」,但我遇到問題,只顯示命令中的第一個文件以打印文本區域,當客戶端終止連接並且另一客戶端嘗試連接到服務器剛剛崩潰的程序確實沒有做任何事情。我究竟做錯了什麼?我認爲問題在於我將指令代碼的一部分「root.mainloop()」,我有這個疑問。如何解決這個失敗? IM堅持This..thanks所有

這裏的客戶端代碼:

#! /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 

##@@-----------------[email protected]@##  

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() 

服務器代碼:

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() 

任何錯誤只是當另一個客戶端試圖程序不告訴我登錄,客戶端界面什麼都不做。

回答

1

我不知道它爲什麼崩潰,但我知道爲什麼只有一個客戶端可以連接。您的服務器僅用於處理多個客戶端。當一個客戶端連接時,所有服務器都會監聽該客戶端 - 任何嘗試連接的其他客戶端都會被忽略。

解決方案很簡單:多線程。爲每個連接的客戶端產生一個新線程,並讓「主」線程接受新的連接。

所得「而(真)」循環應該看起來有點像這樣:

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 

這段代碼(當然,應該)產生一個線程,是以GUI的照顧,同時也將接受連接來自客戶端的請求併爲每個客戶端產生一個新線程,這個客戶端會檢查客戶端的用戶名和密碼,然後持續監聽,直到客戶端斷開連接。