私はpythonを初めて使い、tkinterテキストボックスにサーバのコマンドライン出力を表示するのに問題があります。私はtkinterテキストボックスに何が起こっているのかを表示し、リストボックスにIPアドレスのリストを表示したいと思います。私は本を見ましたが、これをうまく動作させるのに問題があります。私はPython 3.5を使用しています。サーバがtkinterで何をしているかを表示
from tkinter import *
import tkinter as tk
import threading
import socket
import time
import sys
from queue import Queue
import struct
import signal
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
COMMANDS = {'help':['Shows this help'],
'list':['Lists connected clients'],
'select':['Selects a client by its index. Takes index as a parameter'],
'quit':['Stops current connection with a client. To be used when client is selected'],
'shutdown':['Shuts server down'],
}
class MultiServer(object):
def __init__(self):
self.host = ''
self.port = 9999
self.socket = None
self.all_connections = []
self.all_addresses = []
def print_help(self):
for cmd, v in COMMANDS.items():
# print("{0}:\t{1}".format(cmd, v[0]))
self.textBox.insert("{0}:\t{1}".format(cmd, v[0]))
return
def register_signal_handler(self):
signal.signal(signal.SIGINT, self.quit_gracefully)
signal.signal(signal.SIGTERM, self.quit_gracefully)
return
def quit_gracefully(self, signal=None, frame=None):
print('\nQuitting gracefully')
for conn in self.all_connections:
try:
conn.shutdown(2)
conn.close()
except Exception as e:
print('Could not close connection %s' % str(e))
# continue
self.socket.close()
sys.exit(0)
def socket_create(self):
try:
self.socket = socket.socket()
except socket.error as msg:
print("Socket creation error: " + str(msg))
# TODO: Added exit
sys.exit(1)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
return
def socket_bind(self):
""" Bind socket to port and wait for connection from client """
try:
self.socket.bind((self.host, self.port))
self.socket.listen(5)
except socket.error as e:
print("Socket binding error: " + str(e))
time.sleep(5)
self.socket_bind()
return
def accept_connections(self):
""" Accept connections from multiple clients and save to list """
for c in self.all_connections:
c.close()
self.all_connections = []
self.all_addresses = []
while 1:
try:
conn, address = self.socket.accept()
conn.setblocking(1)
client_hostname = conn.recv(1024).decode("utf-8")
address = address + (client_hostname,)
except Exception as e:
print('Error accepting connections: %s' % str(e))
# Loop indefinitely
continue
self.all_connections.append(conn)
self.all_addresses.append(address)
print('\nConnection has been established: {0} ({1})'.format(address[-1], address[0]))
return
def start_turtle(self):
""" Interactive prompt for sending commands remotely """
while True:
cmd = input('turtle> ')
if cmd == 'list':
self.list_connections()
continue
elif 'select' in cmd:
target, conn = self.get_target(cmd)
if conn is not None:
self.send_target_commands(target, conn)
elif cmd == 'shutdown':
queue.task_done()
queue.task_done()
print('Server shutdown')
break
# self.quit_gracefully()
elif cmd == 'help':
self.print_help()
elif cmd == '':
pass
else:
print('Command not recognized')
return
def list_connections(self):
""" List all connections """
results = ''
for i, conn in enumerate(self.all_connections):
try:
conn.send(str.encode(' '))
conn.recv(20480)
except:
del self.all_connections[i]
del self.all_addresses[i]
continue
results += str(i) + ' ' + str(self.all_addresses[i][0]) + ' ' + str(
self.all_addresses[i][1]) + ' ' + str(self.all_addresses[i][2]) + '\n'
print('----- Clients -----' + '\n' + results)
return
def get_target(self, cmd):
""" Select target client
:param cmd:
"""
target = cmd.split(' ')[-1]
try:
target = int(target)
except:
print('Client index should be an integer')
return None, None
try:
conn = self.all_connections[target]
except IndexError:
print('Not a valid selection')
return None, None
print("You are now connected to " + str(self.all_addresses[target][2]))
return target, conn
def read_command_output(self, conn):
""" Read message length and unpack it into an integer
:param conn:
"""
raw_msglen = self.recvall(conn, 4)
if not raw_msglen:
return None
msglen = struct.unpack('>I', raw_msglen)[0]
# Read the message data
return self.recvall(conn, msglen)
def recvall(self, conn, n):
""" Helper function to recv n bytes or return None if EOF is hit
:param n:
:param conn:
"""
# TODO: this can be a static method
data = b''
while len(data) < n:
packet = conn.recv(n - len(data))
if not packet:
return None
data += packet
return data
def send_target_commands(self, target, conn):
""" Connect with remote target client
:param conn:
:param target:
"""
conn.send(str.encode(" "))
cwd_bytes = self.read_command_output(conn)
cwd = str(cwd_bytes, "utf-8")
print(cwd, end="")
while True:
try:
cmd = input()
if len(str.encode(cmd)) > 0:
conn.send(str.encode(cmd))
cmd_output = self.read_command_output(conn)
client_response = str(cmd_output, "utf-8")
print(client_response, end="")
if cmd == 'quit':
break
except Exception as e:
print("Connection was lost %s" %str(e))
break
del self.all_connections[target]
del self.all_addresses[target]
return
def create_workers():
""" Create worker threads (will die when main exits) """
server = MultiServer()
server.register_signal_handler()
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work, args=(server,))
t.daemon = True
t.start()
return
def work(server):
""" Do the next job in the queue (thread for handling connections, another for sending commands)
:param server:
"""
while True:
x = queue.get()
if x == 1:
server.socket_create()
server.socket_bind()
server.accept_connections()
if x == 2:
server.start_turtle()
queue.task_done()
return
def create_jobs():
""" Each list item is a new job """
for x in JOB_NUMBER:
queue.put(x)
queue.join()
return
def main():
create_workers()
create_jobs()
class App(threading.Thread, MultiServer):
def __init__(self):
MultiServer.__init__(self)
threading.Thread.__init__(self)
self.start()
def run(self):
self.root = Tk()
# create all of the main containers
self.top_frame = Frame()
self.center_frame = Frame()
# layout all of the main containers
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(0, weight=1)
self.top_frame.grid(row=0, sticky='NSEW')
self.center_frame.grid(row=1, pady=5, sticky='NSEW')
# Top frame
self.logo = Label(self.top_frame, text='SunGroup')
self.logo.grid(row=0, columnspan=3)
self.command = Entry(self.top_frame, width=25)
self.command.grid(row=1, column=0, padx=5)
self.addButton = Button(self.top_frame, text='Enter', width=5)
self.addButton.grid(row=1, column=1, padx=5)
self.listButton = Button(self.top_frame, text='List', width=5, command=self.list_connections)
self.listButton.grid(row=1, column=2)
self.selectButton = Button(self.top_frame, text='Select', width=5, command=self.get_target)
self.selectButton.grid(row=1, column=3)
self.quitButton = Button(self.top_frame, text='Quit', width=5, command=self.quit_gracefully)
self.quitButton.grid(row=1, column=4)
self.helpButton = Button(self.top_frame, text='Help', width=5, command=self.print_help)
self.helpButton.grid(row=1, column=5)
# Center frame
self.listbox = Listbox(self.center_frame, width=20, height=20)
self.listbox.grid(row=0, column=0, padx=5)
self.textBox = Text(self.center_frame, width=35, height=20)
self.textBox.grid(row=0, column=1, padx=5)
self.textBox.insert(END, self.start_turtle, self.print_help)
self.root.mainloop()
if __name__ == '__main__':
app = App()
main()
SOは個人用のデバッグサービスではありません。[mcve]を投稿してください。 – zwer
コードをすべてポーズするのではなく、あなたの特定の問題に対処するために必要な最小量を投稿してください。必要なのは、tkウィンドウ、テキストボックス、そしておそらくボタンと入力ボックスです。残りはちょうど途中です。その後、あなたが試したことのいくつかの例を与え、私たちはそれを使って作業することができます。 –