написание текстовой области в Python, реализация сокетов - PullRequest
0 голосов
/ 22 февраля 2012

Я выполняю симуляцию сервера печати в python, файлы отправляются с помощью сокетов на сервер, который должен быть помещен в очередь принтера. Когда клиент инициирует связь с сервером, необходимо предоставить идентификатор (пользователя) и ПАРОЛЬ, которые будут проверены по списку на сервере, который можно проверить в файле «passwordlist.txt», который имеет следующий формат:

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

Обе программы должны иметь графический интерфейс на дисплее: * Клиент: поле пользователя, пароль, файл для отправки на печать и отключения от сервера. * Сервер: список файлов, находящихся в очереди на печать На сервере должен отображаться список файлов, которые были правильно отправлены в очередь на печать.

Для этого я решил использовать «текстовую область», но у меня есть проблема, только показывает мне первый файл в команде для печати текстовой области, когда клиент завершает соединение и если другой клиент пытается подключиться к серверу просто сбой программа делает и не делает абсолютно ничего. Что я делаю неправильно? Я думаю, проблема в том, что я помещаю часть кода инструкции «root.mainloop ()», у меня есть это сомнение. как можно решить эту ошибку? я застрял с этим .. спасибо всем

Вот код клиента:

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

Код сервера:

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 Ответ

1 голос
/ 22 февраля 2012

Я не знаю, почему происходит сбой, но я знаю, почему только один клиент может подключиться. Ваш сервер просто не предназначен для работы с несколькими клиентами. Когда один клиент подключается, все, что сервер делает, это слушает этого клиента - любой другой клиент, пытающийся подключиться, просто игнорируется.

Решение простое: многопоточность. Создайте новый поток для каждого подключающегося клиента и разрешите «основному» потоку принимать новые подключения.

Результирующий цикл while (True) должен выглядеть примерно так:

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

Этот код (ну, должен) порождать поток, который заботится о графическом интерфейсе, в то же время он будет принимать запросы на подключение от клиентов и порождать новый поток для каждого клиента, который проверяет имя пользователя и пароль клиента, а затем сохраняет прослушивание, пока клиент не отключится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...