· 8 years ago · Dec 24, 2017, 01:06 PM
1from socket import AF_INET, socket, SOCK_STREAM
2from threading import Thread
3
4# define a dictionary to store the connection socket and the client name
5clients = {}
6# define a dictionary to store the connection socket and the client address
7addresses = {}
8
9HOST = '127.0.0.1'
10PORT = 33007
11BUFSIZ = 1024
12# address tuple containing connection address and port number
13ADDR = (HOST, PORT)
14# create a socket
15SERVER = socket(AF_INET, SOCK_STREAM)
16# associate the socket with the server address and port
17SERVER.bind(ADDR)
18
19
20# accept connections from clients
21def accept_incoming_connections():
22 '''
23 The return value is a pair (connection_socket, client_address) where connection_socket
24 is a new socket object usable to send and receive data on the connection,
25 and client_address is the address bound to the socket on the other end of the connection.
26 So we basically have one listening socket active while the server is running and one
27 new connected socket for each accepted connection which is active until the connection is closed.
28 '''
29 # wait infinitely for new connections
30 while True:
31 # accept the client request
32 client, client_address = SERVER.accept()
33 print("{} has connected".format(client_address))
34 client.send(bytes("Hello there!Please enter your name!", "utf8"))
35 # add the client address to the addresses dictionary
36 addresses[client] = client_address
37 # handle the client
38 Thread(target=handle_client, args=(client,)).start()
39
40
41def handle_client(client):
42 # get the name of the client
43 name = client.recv(BUFSIZ).decode("utf8")
44 # prepare a welcome message to the client
45 welcome = "Welcome {}!To quit please type 'quit'".format(name)
46 # send the welcome message to the client
47 client.send(bytes(welcome, "utf-8"))
48 # prepare a group message
49 message = "{} has joined the chat".format(name)
50 # broadcast the group message to everybody
51 broadcast(bytes(message, "utf8"))
52 # add the client to the clients dictionary
53 clients[client] = name
54 # keep listening for messages
55 while True:
56 # get the message from the client
57 message = client.recv(BUFSIZ)
58 # if message does not contain 'quit'
59 if message != bytes("quit", "utf8"):
60 # broadcast the message to everyone
61 broadcast(message, name + ":")
62 else:
63 # confirm the client you received a 'quit' message
64 client.send(bytes("quit", "utf8"))
65 # close the socket connection
66 client.close()
67 # delete the client entry from the clients dictionary
68 del clients[client]
69 # broadcast everyone that the client has left
70 broadcast(bytes("{} has left the chat".format(name), "utf8"))
71 break
72
73
74def broadcast(message, prefix=""):
75 # prefix gives the name of the person who sent the message
76 # broadcast message to everyone
77 for socket in clients:
78 socket.send(bytes(prefix, "utf8") + message)
79
80
81if __name__ == "__main__":
82 # listen for 5 connections at max
83 SERVER.listen(5)
84 print("Waiting for connection")
85 # create a thread to accept connection
86 accept_thread = Thread(target=accept_incoming_connections)
87 # start the thread
88 accept_thread.start()
89 # wait until the thread has finished executing
90 accept_thread.join()
91 # close the server
92 SERVER.close()
93
94import tkinter
95from socket import AF_INET, socket, SOCK_STREAM
96import sqlite3
97from threading import Thread
98
99
100BUFSIZ = 1024
101# connnect to the database
102db = sqlite3.connect("ChatDB", check_same_thread=False, timeout=5)
103# get a cursor
104cursor = db.cursor()
105create_query = "CREATE TABLE IF NOT EXISTS chatHistory(messages text)"
106# execute the query
107cursor.execute(create_query)
108# execite the query
109result = cursor.execute("SELECT messages FROM chatHistory")
110#rows = cursor.fetchall()
111insert_query = "INSERT INTO chatHistory(messages) VALUES(?)"
112
113# look out for any incoming messages
114def receive():
115 while True:
116 try:
117 # receive the message
118 message = client_socket.recv(BUFSIZ).decode("utf8")
119 message_list.insert(tkinter.END, message) # message_list.insert(index, message)
120 args = (message, )
121 # execute the query
122 cursor.execute(insert_query, args)
123 # commit the changes
124 db.commit()
125 except OSError:
126 break
127
128
129def send(event=None):
130 '''
131 We’re using event as an argument because it is implicitly passed by Tkinter
132 when the send button on the GUI is pressed since an event is triggered.
133 '''
134 # typed_message is the input field on the GUI and we are extracting the message from it
135 message = typed_message.get()
136 args = (message, )
137 # execute the query
138 cursor.execute(insert_query, args)
139 # commit the changes
140 db.commit()
141 # clear the input field
142 typed_message.set("")
143 client_socket.send(bytes(message, "utf8"))
144 if message is "quit":
145 # close the client socket
146 client_socket.close()
147 # close the GUI app
148 window.close()
149
150
151# We define one more function, which will be called when we choose to close the GUI window.
152def on_closing(event=None):
153 # tell the server that you want to quit
154 typed_message.set("quit")
155 # make a call to the send() function
156 send()
157 # destroy the window
158 window.destroy()
159
160
161# create a window
162window = tkinter.Tk()
163# set a title
164window.title("Chat App")
165# create a message frame to display the messages
166message_frame = tkinter.Frame(window)
167# we store the input field of the message frame into a variable
168typed_message = tkinter.StringVar()
169# we put a default message into the message frame
170typed_message.set("Start chatting!")
171# put a scroll bar for the message frame
172scrollbar = tkinter.Scrollbar(message_frame)
173# define a message_list which will list all the messages and it will be stored in the message frame
174message_list = tkinter.Listbox(message_frame, height=15, width=50, yscrollcommand=scrollbar.set)
175# pack the widgets at appropriate places
176scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
177message_list.pack(side=tkinter.LEFT, fill=tkinter.BOTH)
178message_list.pack()
179message_frame.pack()
180# create input field for the user to input their message and bind it to the string variable create above
181entry_field = tkinter.Entry(window, textvariable=typed_message)
182# also bind the input field to the send function so that when user presses 'return', the message is sent
183entry_field.bind("return", send)
184# pack the widgets at appropriate places
185entry_field.pack()
186# create a send button if the user want to press the button to send the message
187send_button = tkinter.Button(window, text="Send", command=send)
188# pack the widgets at appropriate places
189send_button.pack()
190
191'''
192Tkinter supports a mechanism called protocol handlers. Here, the term protocol refers to the
193interaction between the application and the window manager. The most commonly used protocol
194is called WM_DELETE_WINDOW, and is used to define what happens when the user explicitly closes
195a window using the window manager.
196You can use the protocol method to install a handler for this protocol
197'''
198# when the user closes the window, on_closing() method will be called
199window.protocol("WM_DELETE_WINDOW", on_closing)
200
201# ask the user for the host/server address
202HOST = input("Enter host: ")
203# ask the user for the host port
204PORT = input("Enter port: ")
205if not PORT:
206 PORT = 33000 # give a default port if not provided by the user
207else:
208 PORT = int(PORT)
209# address tuple containing connection address and port number
210ADDR = (HOST, PORT)
211# create a client socket
212client_socket = socket(AF_INET, SOCK_STREAM)
213# connect the client socket to the server
214client_socket.connect(ADDR)
215for row in result:
216 message_list.insert(tkinter.END, row)
217# create a thread to receive messages
218receive_thread = Thread(target=receive)
219# start the thread
220receive_thread.start()
221# start the GUI execution
222tkinter.mainloop()