├── README.md ├── chat.gif ├── chat_client.py ├── chat_client_aws.py └── chat_server.py /README.md: -------------------------------------------------------------------------------- 1 | # python-socket-terminal-chat 2 | *This is a simple real time chat application using python socket and Mysql. The application allow multiple users to chat as a group, and it stores chat history on Mysql database. When new user comes, the user can retrieve chat history from Mysql to know what is going on the group chat.* 3 | 4 | ## Installation 5 | $ pip install pymysql 6 | 7 | ## To get these codes run on your local machine 8 | * setup Mysql database on your local machine 9 | * Fill your info in this line db = **pymysql.connect("host","user","pass","db")** on your **chat_server.py** 10 | * create "history" table on Mysql use this command **create table history (message VARCHAR(100));** 11 | 12 | ## A demo of chat_client_aws.py 13 | ![](https://github.com/shenghuayou/python-socket-terminal-chat/blob/master/chat.gif) 14 | -------------------------------------------------------------------------------- /chat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenghuayou/python-socket-terminal-chat/1be406cddc11cb06f428f9331233c2757f338ba2/chat.gif -------------------------------------------------------------------------------- /chat_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import socket 4 | from threading import Thread 5 | import sys 6 | 7 | # basic socket setup for client 8 | TCP_IP = 'localhost' 9 | TCP_PORT = 6666 10 | BUFFER_SIZE = 1024 11 | username = input('enter a username: ') 12 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 13 | s.connect((TCP_IP, TCP_PORT)) 14 | 15 | # send username to server 16 | s.send(username.encode('utf-8')) 17 | 18 | # recv function keep running on thread 19 | def recv(): 20 | while 1: 21 | data = s.recv(BUFFER_SIZE) 22 | if data: 23 | print (data.decode('utf-8')) 24 | Thread(target=recv).start() 25 | 26 | # user will keep doing input 27 | while 1: 28 | input_message = input('') 29 | MESSAGE = ('%s: %s' % (username,input_message)) 30 | s.send(MESSAGE.encode('utf-8')) 31 | 32 | s.close() -------------------------------------------------------------------------------- /chat_client_aws.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # this client connects to the server that I host on aws, free to chat 4 | 5 | import socket 6 | from threading import Thread 7 | import sys 8 | 9 | # basic socket setup for client 10 | TCP_IP = '54.149.37.172' 11 | TCP_PORT = 6666 12 | BUFFER_SIZE = 1024 13 | username = input('enter a username: ') 14 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 15 | s.connect((TCP_IP, TCP_PORT)) 16 | 17 | # send username to server 18 | s.send(username.encode('utf-8')) 19 | 20 | # recv function keep running on thread 21 | def recv(): 22 | while 1: 23 | data = s.recv(BUFFER_SIZE) 24 | if data: 25 | print (data.decode('utf-8')) 26 | Thread(target=recv).start() 27 | 28 | # user will keep doing input 29 | while 1: 30 | input_message = input('') 31 | MESSAGE = ('%s: %s' % (username,input_message)) 32 | s.send(MESSAGE.encode('utf-8')) 33 | 34 | s.close() -------------------------------------------------------------------------------- /chat_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import select 4 | import socket 5 | import sys 6 | import pymysql 7 | import time 8 | 9 | def store_message(info): 10 | # connect to database and store data 11 | db = pymysql.connect("host","user","pass","db" ) 12 | cursor = db.cursor() 13 | cursor.execute("insert into history(message) values (%s);", info) 14 | db.commit() 15 | db.close() 16 | 17 | def read_message(): 18 | # connect to database and retrieve data 19 | return_list=[] 20 | db = pymysql.connect("host","user","pass","db" ) 21 | cursor = db.cursor() 22 | cursor.execute("select * from history") 23 | result = cursor.fetchall() 24 | for i in result: 25 | return_list.append(i[0]) 26 | db.close() 27 | return (return_list) 28 | 29 | def broadcast (server_socket, sock, message): 30 | for socket in input: 31 | # send message to all clients exceot itself 32 | if socket != server_socket and socket != sock: 33 | try : 34 | socket.send(message) 35 | except : 36 | socket.close() 37 | if socket in input: 38 | input.remove(socket) 39 | 40 | 41 | # basic socket setup for server 42 | host = 'localhost' 43 | backlog = 5 44 | BUFFER_SIZE = 1024 45 | port = 6666 46 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 47 | server.bind((host,port)) 48 | server.listen(backlog) 49 | input = [server,] # list of connection 50 | 51 | # dict for client and username 52 | client_username_dict = {} 53 | 54 | print ('server is up, waiting for connections') 55 | while 1: 56 | inputready,outputready,exceptready = select.select(input,[],[]) 57 | 58 | for s in inputready: #check each socket that select() said has available data 59 | if s == server: #if select returns our server socket, there is a new 60 | #remote socket trying to connect 61 | client, address = server.accept() 62 | input.append(client) #add it to the socket list 63 | print ('New client: %s'%str(address)) 64 | 65 | #decode username from client, and add it to dictionary 66 | username_data = client.recv(BUFFER_SIZE) 67 | decoded_username_data = username_data.decode('utf-8') 68 | client_username_dict[client] = decoded_username_data 69 | 70 | # tell connected client that a new client connects to server 71 | enter_data ="---------------" + str(decoded_username_data) + " enter the room" + "---------------" 72 | encode_enter_data = enter_data.encode('utf-8') 73 | broadcast(server,client,encode_enter_data) 74 | 75 | # send chat history to a new client 76 | history_list = read_message() 77 | for i in history_list: 78 | client.send(i.encode('utf-8')) 79 | time.sleep(0.01) 80 | 81 | else: 82 | # select has indicated that these sockets have data available to recv 83 | data = s.recv(BUFFER_SIZE) 84 | if data: 85 | decode_data = str(data.decode('utf-8')) 86 | store_message(decode_data) 87 | broadcast(server, s, data) 88 | else: 89 | #send out message when a client left 90 | left_user = client_username_dict[s] 91 | left_data = "---------------" + str(left_user) + " left the room" + "---------------" 92 | broadcast(server,s,left_data.encode('utf-8')) 93 | 94 | # remove this client from dictionary and socket list 95 | del client_username_dict[s] 96 | s.close() 97 | input.remove(s) 98 | 99 | server.close() --------------------------------------------------------------------------------