Es ist @ seigo2016 der N High School Programmierklasse 1. Jahr. Es wird [N High Adcare Day 8] sein (https://qiita.com/advent-calendar/2019/n-highschool). Ich habe mich gefragt, was ich schreiben soll, weil es ein richtiger Artikel ist, aber da ich viel über das aktuelle Hauptprojekt "Itokake Mandara Color Simulator" bei U22 usw. gesprochen habe, habe ich diesmal viel über das aktuelle Kurzzeitprojekt "PSS ~ Presentation Support" gesprochen. Ich werde über "System ~" sprechen.
Ich denke, dass Sie häufig Präsentationen mit PowerPoint, Google Slide usw. halten, wenn Sie Leuten etwas erzählen. LT wird auch jeden Monat in der N High Programming Class (im Folgenden als Prokura bezeichnet) abgehalten. Deshalb habe ich beschlossen, ein System zur Unterstützung der Präsentation zu erstellen.
Es ist der Teil, der Kommentare akzeptiert und aufzeichnet. Alles läuft auf Docker. Der Speicher ist 1 GB groß, funktioniert aber unerwartet.
Teil | Performance |
---|---|
VPN | Vultr |
CPU | 1C/1T |
Memory | 1024MB |
OS | OS Debian 10 Buster |
Ich benutze es auch, um Docker und Docker-Compose zu üben.
Containername | Überblick |
---|---|
proxy | Nginx Reverse Proxy |
web | Python3.6(Python ausführen) |
mysql | DB(Speichern Sie die Anmeldeinformationen) |
Ich habe bcrypt verwendet, um das Passwort zu hashen, und die MySQL-Connector-Bibliothek, um eine Verbindung zu MySQL herzustellen. Zusätzlich zu den folgenden wurden SSL und Socket verwendet.
Python3
bcrypt==3.1.7
mysql-connector==2.2.9
pycrypto==2.6.1
PyYAML==5.2
tornado==6.0.3
Ich habe Tkinter als Bibliothek zum Erstellen der GUI verwendet.
Python3
pdf2image==1.10.0
Pillow==6.2.1
progressbar2==3.47.0
PyYAML==5.2
Dies ist der Hauptteil dieses Projekts. Das System selbst, in dem Kommentare in Echtzeit eingehen, wurde bereits von anderen professionellen Clubstudenten erstellt. Es gab jedoch viele Einschränkungen, z. B. die Nichtverwendung, wenn die Verbindungen zwischen Clients getrennt wurden. Daher haben wir beschlossen, ein neues System zu erstellen, das diese Teile verbessert. ** Dieses System verstößt nicht gegen das Patent des Kommentarsystems von Dongo, da die Montagemethode und die technischen Daten völlig unterschiedlich sind ** So funktioniert es.
Abgesehen davon gibt es mehrere Personen in meiner Umgebung, die Schwachstellen finden und melden möchten. Daher sind einige Sicherheitsmaßnahmen erforderlich, um zu verhindern, dass sie in die eigentliche Präsentation aufgenommen werden.
Dies ist der Teil, der Kommentare akzeptiert. Der Fluss ist wie folgt.
server.py
def send_comment(comment):
#Aktuelle Uhrzeit(JST)
dt_now = dt.now(JST)
#In Datenbank aufnehmen
c = database.cursor()
sql = "INSERT INTO comment (text, entertime) values(%s,%s)"
c.execute(sql,
(comment, dt_now,))
database.commit()
#Weisen Sie einer Variablen zu, die von Threads gemeinsam genutzt wird
with commentbody.get_lock():
commentbody.value = comment.encode()
class Comment(web.RequestHandler):
def post(self):
comment = self.get_argument("comment")
comment = escape(comment)
title = "Kommentar"
if re.search(r'\S', comment) and len(comment) < 30:
send_comment(comment)
self.render('index.html', title=title)
else:
message = "Eingabe korrekt"
self.render('index.html', title=title, message=message)
Als nächstes ist es der Teil, der den empfangenen Kommentar per Socket-Kommunikation an den Client (Präsentator-PC) sendet. Der Fluss ist wie folgt.
server.py
def connect_socket(): #Socket-Kommunikation
print("SocketStart")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('0.0.0.0', 10023)) #Öffnen Sie an Port 10023
while True:
s.listen(1)
print("Waitng ....")
conn, addr = s.accept()
flg = False
while True:
try:
conn = context.wrap_socket(conn, server_side=3)
with conn:
while True:
try:
print("Connecting")
data = conn.recv(1024).decode()
if not data:
break
elif ":" in data:
loginuser = data.split(":")[0]
loginpass = data.split(":")[1]
sql = "SELECT id, name, pass FROM users WHERE name = %s"
c.execute(sql, (loginuser,))
userdata = c.fetchall()
if len(userdata) and bcrypt.checkpw(loginpass.encode(), userdata[0][2].encode()):
print("Connected")
conn.sendall("Verbindung hergestellt".encode("utf-8"))
flg = True
else:
conn.sendall("Authentifizierungsfehler".encode("utf-8"))
conn.close()
flg = False
elif flg:
comment = commentbody.value
with commentbody.get_lock():
commentbody.value = "".encode()
if len(comment):
conn.sendall(comment)
comment = ""
except socket.error:
flg = False
break
except Exception as e:
flg = False
print("Disconnected\n{}".format(e))
s.close()
Nach dem Herstellen einer Verbindung zum Server, dem Senden der Authentifizierungsinformationen und dem Anmelden erhält der Client (Präsentations-PC) den Kommentar.
client.py
def rcv_comment():
#Einstellungen für die Socket-Kommunikation
context = ssl.create_default_context()
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_NONE
context.check_hostname = False
conn = context.wrap_socket(socket.socket(socket.AF_INET),
server_hostname=host)
conn.connect((host, port))
#Bereiten Sie Authentifizierungsinformationen vor(Das Format ist Benutzer:pass)
idpass = "{}:{}".format(user_name, user_pass).encode()
conn.sendall(idpass)
manager = CommentManager(canvas)
while True:
try:
data = conn.recv(1024)
if len(data):
comment = data.decode('utf-8')
print("recv:" + comment)
#Wenn ein Authentifizierungsfehler zurückgegeben wird, schließen Sie das Programm ab
if comment == "Authentifizierungsfehler":
break
#Andernfalls übergeben Sie den Kommentar an das Zeichnungsteil
manager.add_text(comment)
except KeyboardInterrupt:
break
Zeichnen Sie den erhaltenen Kommentar auf Tkinters Leinwand.
client.py
class CommentManager: #Zeichnungskommentare verwalten
def __init__(self, canvas):
self.canvas_text_list = []
self.canvas = canvas
root.after(1, self.update)
def add_text(self, comment): #Fügen Sie einen Kommentar zum Flow hinzu
#Generieren Sie Text mit einer x-Koordinate am Rand des Bildschirms und einer zufälligen y-Koordinate
text = self.canvas.create_text(
w, random.uniform(2.0, 18.0) * 100, text=comment, font=comment_font)
self.canvas_text_list.append(text)
def update(self): #Gehe nach links
new_list = []
#Verschieben Sie Kommentare in der Liste nach links.(Es scheint besser, alles auf einmal mit Tags zu tun)
for canvas_text in self.canvas_text_list:
self.canvas.move(canvas_text, -15, 0)
x, y = self.canvas.coords(canvas_text)
if x > -10:
new_list.append(canvas_text)
else: #Nach dem Umzug zum linken Ende
self.canvas.delete(canvas_text)
self.canvas_text_list = new_list
root.after(20, self.update)
Da die Folie selbst in Tkinters Canvas geladen wird, aktualisieren Sie einfach das Bild
client.py
def next(event): #Folie senden
global page
if pagemax - 1 > page:
canvas.itemconfig(labelimg, image=img[page])
page += 1
def prev(event): #Bewegen Sie den Schlitten zurück
global page
if 0 <= page:
canvas.itemconfig(labelimg, image=img[page])
page -= 1
# ~Unterlassung~ #
if __name__ == '__main__':
th = Thread(target=rcv_comment)
th.setDaemon(True)
th.start()
root.bind("<Key-n>", next) #Schlüssel hier zuweisen
root.bind("<Key-p>", prev)
root.mainloop()
Es ist nicht implementiert, da ich mir Sorgen mache, welches als Zeigergerät verwendet werden soll. Ich werde es hinzufügen, sobald es implementiert ist. Ist ein Smartphone doch gut?
Ich schreibe wütenden Code, der überhaupt nicht gepackt ist ... Die Leistung ist nicht gut, wenn eine große Anzahl von Kommentaren fließt. Ich denke, es wäre ratsam, es als Overlay anzuzeigen.
Recommended Posts