Ein Chat in Python (Ein Chat in Python), Lektion, Seite 724723
https://www.purl.org/stefan_ram/pub/chat_python (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Python-Kurs

Ein Chat in Python 

LAN_chat.pyw
import datetime
import io
import math
import os
import pathlib
import re
import socket
import sys
import threading
import time
import tkinter
import tkinter.messagebox
from tkinter import font
root = tkinter.Tk()
root.withdraw()
progname="Stefan Ram's LAN chat"
versionname=progname +" (Version 2020-09-14/--24)"
def startup():
global file
shared_dir_ = r"X:\Alle"
shared_dir = pathlib.Path( shared_dir_ )
if not shared_dir.is_dir():
tkinter.messagebox.showerror( progname, f'There is no directory "{shared_dir_}"!' )
sys.exit( 99 )
file = shared_dir_ + r"\chatfile_fvmchmpqtx.txt"
startup()
def follow():
first_opening = True
while True:
try:
with open( file, encoding="utf_8" ) as input:
if first_opening:
# SEEK_END = 2; input.seek( 0, SEEK_END )
input.seek( stream_pos, io.SEEK_SET )
first_opening = False
latest_data = input.read()
while True:
if '\n' not in latest_data:
latest_data += input.read()
if '\n' not in latest_data:
yield ''
if not os.path.isfile( file ):
break
continue
latest_lines = latest_data.split( '\n' )
if latest_data[ -1 ]!= '\n':
latest_data = latest_lines[ -1 ]
else:
latest_data = input.read()
for line in latest_lines[:-1]:
yield line + '\n'
except OSError as oserror:
if oserror.errno == 2:
time.sleep( 3 )
def receive():
for msg in follow():
if exiting: return
if msg == "":
if exiting: return
root.config( cursor="" )
time.sleep( 1 )
else:
root.config( cursor="wait" )
try:
#print( f"received: \"{msg}\"." )
if exiting: return
listbox.insert( tkinter.END, msg )
listbox.yview( tkinter.END )
if re.match( r"^\d\d\d\d-\d\d-\d\dT.*", msg ):
listbox.itemconfig( tkinter.END, bg='lightgray' )
except OSError as oserror:
print( oserror )
break
def entrybox_send( event=None ):
msg = entrybox.get( "1.0", "end-1c" )
entrybox.delete( "1.0", tkinter.END )
try:
with open( file, "a", encoding="utf_8" ) as output:
output.write( datetime.datetime.now( datetime.timezone.utc ).astimezone().isoformat( 'T' ) + "\n" )
output.write( msg + "\n" )
os.system('attrib +H ' + file + ' /S')
except exception as e:
print( tkinter.END, "\nentrybox_send: append failed." )
if msg == "exit":
root.quit()
def on_closing( event=None ):
global exiting
exiting = True
root.destroy()
height=16
width=16
image=tkinter.PhotoImage(height=16, width=width)
image.blank()
for x in range( width ):
for y in range( height ):
image.put( "#ffffff",( x, y ))
for x in range( width ):
for y in range( 11, 14 ):
image.put( "#000000",( x, y ))
root.wm_iconphoto('True', image)
root.title( versionname )
def f():
while not exiting:
root.title( versionname + " " + datetime.datetime.now( datetime.timezone.utc ).astimezone().isoformat( 'T' ) )
time.sleep( 1 )
messages = tkinter.Frame( root )
scrollbar = tkinter.Scrollbar( messages )
small_font = font.nametofont("TkFixedFont")
small_font.configure(size=20,weight="bold")
listbox = tkinter.Listbox( messages, height=1, width=1, yscrollcommand=scrollbar.set, selectmode=tkinter.EXTENDED, font=small_font )
scrollbar.pack( side=tkinter.RIGHT, fill=tkinter.Y )
scrollbar.config(command=listbox.yview) # call list.yview when I move
listbox.config(yscrollcommand=scrollbar.set) # call sbar.set when I move
listbox.pack( side=tkinter.LEFT, expand=1, fill=tkinter.BOTH )
messages.pack( expand=1, fill=tkinter.BOTH )
from tkinter.scrolledtext import ScrolledText
entrybox = ScrolledText( root, height=5 )
entrybox.bind( "<Control-KeyRelease-Return>", entrybox_send )
entrybox.pack( side=tkinter.LEFT, expand=1, fill=tkinter.X )
send_button = tkinter.Button( root, text="Send", command=entrybox_send )
send_button.pack( side=tkinter.RIGHT )
entrybox.focus_set()
root.geometry( "512x383" )
root.protocol( "WM_DELETE_WINDOW", on_closing )
root.deiconify()
stream_pos = 0
# on the main thread, to suppress screen updating
try:
with open( file, encoding="utf_8" ) as input:
latest_data = input.read()
stream_pos = input.tell()
latest_lines = latest_data.split( '\n' )
root.config( cursor="wait" )
for line in latest_lines[:-1]:
listbox.insert( tkinter.END, line )
listbox.yview( tkinter.END )
if re.match( r"^\d\d\d\d-\d\d-\d\dT.*", line ):
listbox.itemconfig( tkinter.END, bg='lightgray' )
root.config( cursor="" )
except OSError as oserror:
pass
exiting = False
freceive_thread = threading.Thread( target=f )
freceive_thread.start()
receive_thread = threading.Thread( target=receive )
receive_thread.start()
tkinter.mainloop()
socket chat server

import socket

import threading

def serve():

while True:

client, address = server_socket.accept()

print( f"{address} has connected." )

client.send( bytes( "Connection accepted.\r\n", "utf_8") )

clientdict[ client ]= address

threading.Thread( target=handle_client, args=( client, )).start()

def handle_client( client ):

while True:

try:

data = client.recv( size )

text = data.decode()

print( f"received: \"{text}\"" )

if text == "exit":

dismiss( client )

break

else:

distribute( data )

except:

print( "handle_client: error in send." )

dismiss( client )

break

def distribute( data ):

for client in clientdict.copy():

try:

client.send( data )

except:

print( "distribute: error in send." )

dismiss( client )

continue

def dismiss( client ):

print( "dimissing client." )

try:

client.send( bytes( "exit", "utf_8" ))

except:

pass

client.close()

del clientdict[ client ]

print( f"{socket.gethostbyname_ex( socket.gethostname() ) = }" )

clientdict = {}

size = 1024

server_socket = socket.socket( socket.AF_INET, socket.SOCK_STREAM )

server_socket.bind( ( '', 33001 ))

if __name__ == "__main__":

server_socket.listen( 5 )

print( "Server is running." )

thread = threading.Thread( target=serve )

thread.start()

thread.join()

server_socket.close()

socket chat client

import math

import socket

import threading

import tkinter

def receive():

while True:

try:

msg = server.recv( size ).decode( "utf_8 ")

print( f"received: \"{msg}\"." )

listbox.insert( tkinter.END, msg )

except OSError:

break

def entrybox_send( event=None ):

msg = inputvar.get()

inputvar.set( "" )

try:

server.send( bytes( msg, "utf_8" ))

except:

print( tkinter.END, "\nentrybox_send: server.send failed." )

if msg == "exit":

server.close()

tk.quit()

def on_closing( event=None ):

try:

server.send( bytes( "exit", "utf_8" ))

except:

print( "\non_closing: server.send failed." )

try:

server.close()

except:

print( "\non_closing: server.close failed." )

tk.destroy()

tk = tkinter.Tk()

height=16

width=16

image=tkinter.PhotoImage(height=16, width=width)

image.blank()

for x in range( width ):

for y in range( height ):

image.put( "#ffffff",( x, y ))

for x in range( width ):

for y in range( 11, 14 ):

image.put( "#000000",( x, y ))

tk.wm_iconphoto('True', image)

tk.title( "Chat" )

messages = tkinter.Frame( tk )

inputvar = tkinter.StringVar()

scrollbar = tkinter.Scrollbar( messages )

listbox = tkinter.Listbox( messages, height=1, width=1, yscrollcommand=scrollbar.set )

scrollbar.pack( side=tkinter.RIGHT, fill=tkinter.Y )

listbox.pack( side=tkinter.LEFT, expand=1, fill=tkinter.BOTH )

messages.pack( expand=1, fill=tkinter.BOTH )

entrybox = tkinter.Entry( tk, textvariable=inputvar )

entrybox.bind( "<Return>", entrybox_send )

entrybox.pack( side=tkinter.LEFT, expand=1, fill=tkinter.X )

send_button = tkinter.Button( tk, text="Send", command=entrybox_send )

send_button.pack( side=tkinter.RIGHT )

tk.geometry( "512x383" )

tk.protocol( "WM_DELETE_WINDOW", on_closing )

host = input( 'server address: ' )

if not host:

host = "localhost"

size = 1024

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.connect( ( host, 33001 ))

receive_thread = threading.Thread( target=receive )

receive_thread.start()

tkinter.mainloop()

 

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram724723 stefan_ram:724723 Ein Chat in Python Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd724723, slrprddef724723, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/chat_python