Tkinter gui with client server in Python - python

I have used a Tkinter to create a simple gui with client server running . However, I can get the client server communicating for what ever reason . Can someone look at my code an tell me why it is not working
Server :
import Tkinter as tk
import os
import socket # Required to allow network communicate
import re
w, h = 500, 200
connection = None
def key(self, event):
self.frame.focus_force()
connection.send(event.keysym) # Sends the command to the robot
def SendEnterCommand(event): # Bound to the Enter key
connection.send("enter") # Sends the command to the robot
print('Sent Message - Enter') # Feedback for the controller
def SendSpaceCommand(event): # Bound to the Space key
connection.send("space") # Sends the command to the robot
print('Sent Message - Space')# Feedback for the controller
def SendKillCommand(event): # Bound to the Escape key
connection.send("kill") # Sends the command to the robot
print('Sent Message - Kill')# Feedback for the controller
# Used to check if the IP address follows the correct format
def CheckIP(IP):
pat = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") # Check if the ip address value inputted follows the form of an ip address
test = pat.match(IP)
if test:
return True
else:
return False
def UpdateConnection(IPAddress, Port):
currentCommand = "empty"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
serversocket.bind((IPAddress, Port)) # Set up the socket on YOUR IP address and selected port
serversocket.listen(5) # Listen on the socket, up to 5 backlogged connections
print('waiting for a connection')
connection, client_address = serversocket.accept() # Wait for a connection, when there is one accept it
print ('Connected with ' + client_address[0] + ':' + str(client_address[1])) # Print who we are connected to
data = ""
while data != 'Kill': # Loop until the escape key is pressed
root.update()
def SetUpConnection():
IPAddress = IPEntry.get()
Port = int(PortEntry.get())
if CheckIP(IPAddress) and isinstance( Port, int ) and Port > 0 and Port < 9999: # check if the ip address is of the correct format, check if the port is an integer and greater than 0
#if InputMethodSelection.get() >= 1 and InputMethodSelection.get() <= 4: # check if there is a valid selected input option
print( "Connecting", "Connecting To Server!")
UpdateConnection(IPAddress, Port) # Connect and run the server
#else:
# print( "ERROR", "Select an input type!")
else:
tkMessageBox.showinfo( "ERROR", "Invalid IP address or port")
# Add a couple widgets. We're going to put pygame in `embed`.
root = tk.Tk()
embed = tk.Frame(root, width=w, height=h)
embed.pack()
BroadcastBTN = tk.Button(root, text='Broadcast', command=SetUpConnection)
BroadcastBTN.pack()
tk.Label(root, text="IP:").pack(anchor = "w")
IPEntry = tk.Entry(root)
IPEntry.config(width=20)
IPEntry.pack(anchor = "w")
tk.Label(root, text="Port:").pack(anchor = "w")
PortEntry = tk.Entry(root)
PortEntry.config(width=10)
PortEntry.pack(anchor = "w")
# Show the window so it's assigned an ID.
root.update()
root.bind("<Key>", key)
root.bind("<Return>", SendEnterCommand)
root.bind("<space>", SendSpaceCommand)
root.bind("<Escape>", SendKillCommand)
root.mainloop()
Client:
import socket # Required to allow network
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Initialise the socket
print('Connecting') # user guidance output
sock.connect(("192.168.1.59", 9559))
data = ""
print('I AM CONNECTED') # user guidance output
while data != 'Kill': # Loop until the computer tries to close the connection
data = sock.recv(1024) # Recieve data from the connection
if(data == "EnterPressed"):
print("Enter Pressed")
elif(data == "space"):
print("Space Pressed")
elif(data == "forward"):
print("Forward Pressed")
elif(data == "left"):
print("Left Pressed")
elif(data == "right"):
print("Right Pressed")
elif(data == "backward"):
print("Backward Pressed")
elif(data == "pressed"):
print("pressed Pressed")
else:
print(data)
sock.close()
print('DISCONNECTED') # user guidance output

Related

Python multiclient server

I want to create a TCP server which can send specific messages to specific clients. In my example, I have two clients Iconet and Robot. I want to send specific messages to each of these clients once they are connected. I wish to send VITAi and VITAr to the clients respectively. Once i receive the response from the two clients i wish to jump to def chat() The aim is to get the response from clients and then jump to def chat() which acts like a chat room and displays the messages the clients have sent. How can i achieve this?
server
import threading
import socket
PORT = 1026
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER,PORT)
FORMAT = "utf-8"
HEADER = 1024
DISCONNECT_MESSAGE = "END_CYCLE"
VITA_R = "yes"
VITA_I = "yes"
robot_flag = False
iconet_flag = False
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
clients = []
aliases = []
alias_dictionary_iter = zip(aliases,clients)
alias_dictionary = dict(alias_dictionary_iter)
def broadcast(broadcast_message):
for client in clients:
client.send(broadcast_message)
def handle_client(client,addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
for client in clients:
if client == clients[0]:
robot_message = 'VITAr'
client.send(robot_message.encode(FORMAT))
robot_response = client.recv(2048).decode(FORMAT)
print(robot_response)
if robot_response == VITA_R:
robot_flag == True
else:
robot_flag == False
elif client == clients[1]:
iconet_message = 'VITAi'
client.send(iconet_message.encode(FORMAT))
iconet_response = client.recv(2048).decode(FORMAT)
print(iconet_response)
if iconet_response == VITA_I:
iconet_flag == True
else:
iconet_flag == False
def chat(client):
while robot_flag & iconet_flag == True:
try:
message = client.recv(1024)
broadcast(message)
print(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
alias = aliases[index]
broadcast(f'{alias} has left the chat room!'.encode('utf-8'))
aliases.remove(alias)
break
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
client, addr = server.accept()
print(f"[NEW CONNECTION] {addr} connected.")
client.send('NAME?'.encode(FORMAT))
alias = client.recv(1024)
aliases.append(alias)
clients.append(client)
print(f'The clients is {alias}'.encode(FORMAT))
thread = threading.Thread(target= handle_client, args=(client, addr))
thread.start()
print ('[STARTING] server is starting')
start()
client
import threading
import socket
name = input('NAME? ')
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('0.0.0.0', 1026))
def client_receive():
while True:
try:
message = client.recv(1024).decode('utf-8')
if message == "NAME?":
client.send(name.encode('utf-8'))
else:
print(message)
except:
print('Error!')
client.close()
break
def client_send():
while True:
message = f'{name}: {input("")}'
client.send(message.encode('utf-8'))
receive_thread = threading.Thread(target=client_receive)
receive_thread.start()
send_thread = threading.Thread(target=client_send)
send_thread.start()

Connect sql server to Python3 - client-server

i'm new in socket programming with python i wrote some code for client and server that is not completed.
i want to connect my server side to Sql server dbms to store data there (this is a student management system) i want to send some data from client side then server side store them on data base and when got asked by client return them.
Here is my both side codes:
this is client:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host ="127.0.0.1"
port =8000
def send(message):
message=str(message)
s.send(message.encode())
data = s.recv(1024).decode()
print (data)
def end():
s.close ()
def menu1():
print("Data has been saved to DB!\nWhat you need next?\n1.Close Connection.\n2.Enter More Data.\n3.Get Data.")
while 1:
m=input()
if int(m)==1:
end()
elif int(m)==2:
enter_data()
elif int(m)==3:
get_data()
else:
print("Choose a Num between 1-3!\n")
def enter_data():
flag=0
while 1:
if flag==0:
r = input('enter amount of student: ')
for i in range (0,int(r)):
name=input("Enter Student %d name"%(i))
send(name)
break
menu1()
def start():
s.connect((host,port))
print("You are connected to server!")
print("1.Enter Data")
print("2.Get Data")
m=input()
if int(m)==1:
enter_data()
elif int(m)==2:
end()
def menu():
m = input("press any key to connect!\n");
start()
if __name__ == "__main__":
menu()
and this is server side code:
import socket
from threading import *
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = ""
port = 8000
#print (host)
#print (port)
serversocket.bind((host, port))
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
#amount=self.sock.recv(1024).decode()
#amount=int(amount)
#counter=0
while 1:
api=self.sock.recv(1024).decode()
#print(self.sock.recv(1024).decode())
print("Client sent some messages: %s"%(api))
#api=self.sock.recv(1024).decode()
if str(api)=="avarage":
avarage=2/10
c=str(avarage)
self.sock.send(c.encode())
else:
avarage = 3 / 10
c = str(avarage)
self.sock.send(c.encode())
serversocket.listen(5)
print ("server started and listening to port:%s"%(port))
while 1:
clientsocket, address = serversocket.accept()
client(clientsocket, address)
I'm a bit new in this type of programming so please give me a part of code that i need to add.
thanks in advance.
I know that some parts of this code is not usable i just wrote them for test some things and get the concept of that.
also when i want to close connection server side i got this error:
File "C:/Users/name/PycharmProjects/Socket/venv/Socket1.py", line 23, in run
api=self.sock.recv(1024).decode()
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

Multithreading does not work for bi-directional udp communication python

Output at console server
I am trying to write bi-directional UDP communication using multithread but it crashes after sending two messages. Also i am new to threading so please post your solution on this.
Thanks
Server side:
import threading
from threading import Thread
import socket
from socket import *
import time
import pymongo
from datetime import datetime
from time import ctime
#broadcast works for this program
import netifaces
import os
import re
import struct
class cont():
def get_msg(self):
UDP = "192.168.1.27"
port = 4343
address = UDP, port
self.sock = socket(AF_INET, SOCK_DGRAM)
self.sock.bind(address)
while True:
r = self.sock.recvfrom(1000)
print("controller1: %s" % (r[0]))
reply = input('Main controller : ')
client_address = r[1]
self.sock.sendto(bytearray(reply, "utf-8"), client_address)
t2 = threading.Thread(target=self.get_msg, args=(reply,))
t2.start()
if __name__=='__main__':
c=cont()
#c.broad(msg="")
c.get_msg()
Client side:
UDP=""
port=4343
address=UDP,port
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while(True):
msg=input("Controller1")
client.sendto(bytearray(msg,"utf-8"),address)
reply=client.recvfrom(1000)
recved=str(reply)
print("Main Controller:% s" % recved))
Output required :
Server Console:
Client:b'hello'
Server:b'hi
Client Console:
Client: b'hello'
Server : (b'hi',('ip',port)
Here is a TCP class I made for communicating with my robots, can be easily modified for UDP. Might seem like a lot of code, but it's what it takes for "reliable" "two way" communication, without blocking your main program. I use processes instead of threads because threads in python aren't "real" threads due to the global interpreter lock.
import socket
from multiprocessing import Process, Queue, Event, Value
import traceback
class SocketComm(object):
def __init__(self,port):
self.address = ""
self.otherAddress = object
self.port = port
self.finished = Value("b", True)
self.inbox = Queue()
self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.getMessagesProcess = Process(target=self.getMessages)
self.getMessagesProcess._stop_event = Event()
self.getMessagesProcess.daemon = True
self.connected = False
self.timeout = 3
return
def setupLine(self, addr):
self.address = addr
if self.address is "": #i.e. server on raspberry pi
try:
self.connection.settimeout(self.timeout)
self.connection.bind((self.address, self.port))
print("binding with port: " + str(self.port))
self.connection.listen(1)
self.connection, self.otherAddress = self.connection.accept()
print("connected to client at: " + self.otherAddress[0])
except socket.error as e:
print(str(e))
return False
else:
try:
#print("connecting to port: " + str(self.port))
self.connection.connect((self.address, self.port)) # i.e. client
print("connected to server")
except socket.error as e:
#print(str(e))
return False
self.getMessagesProcess.start()
self.connected = True
self.finished.value = False
print("inbox at: " + str(id(self.inbox)))
return True
def sendMessage(self, msg):
try:
self.connection.send(str.encode(msg))
#print("sent: " + str(msg))
except Exception as e:
pass
#print(str(e))
#traceback.print_exc()
#print("exception caught.")
return
def getMessages(self):
#print("getting messages now")
self.connection.settimeout(1)
while(not self.finished.value):
#print("checking inbox")
#print("inbox length: " + str(len(self.inbox)))
try:
received = self.connection.recv(1024)
decoded = received.decode('utf-8')
if len(decoded) > 0:
if(decoded == "end"):
self.finished.value = True
else:
self.inbox.put(decoded)
print("received: " + str(decoded))
except socket.error as e:
if(type(e).__name__ == "timeout"):
pass
else:
print("endpoint closed.")
self.finished.value = True
return
def closeConnection(self):
if(self.connected):
self.finished.value = True
self.getMessagesProcess._stop_event.set()
self.sendMessage("end")
try:
self.getMessagesProcess.join()
except:
print("process already finished.")
self.connection.close()
return
##
##if(__name__ == "__main__"):
## robotClient = SocketComm(5555)
## robotClient.setupLine("127.0.0.1")
## while(robotClient.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotClient.sendMessage(val)
##
##
##if(__name__ == "__main__"):
## try:
## robotServer = SocketComm(5555)
## print("waiting for client to connect...")
## robotServer.setupLine("")
## print("connected!")
## while(robotServer.finished.value == False):
## val = input("enter something: ")
## if(len(val) > 0):
## robotServer.sendMessage(val)
## except:
## pass
## finally:
## robotServer.closeConnection()
## sys.exit(0)

python thread waits for input before it prints

I'm writing a socket communication program, I have a main thread, and another thread trying to sock.recv()
when it does recieve bytes, it works as it needs, it goes to the right function, which at the end prints, and then the thread listens again to bytes (as wanted).
the problem is that the program won't print until I press enter...
if it matters i'm getting input at the same time in the main thread but it shouldn't matter.
note - the bytes are sent like this:
int (4 bytes) - msg type (string to print is 2)
int (4 bytes) - length of text to print
string ( bytes) - actual text
full code:
import socket
import time
import struct
import threading
import sys
PORT = 54321
def try_to_connect(ip):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
socket.IPPROTO_TCP)
sock.settimeout(1)
try:
sock.connect((ip, PORT))
return sock
except:
return False
def text_parse(text, msg_id):
byte_text = bytes(text, "utf-8")
return struct.pack("II%ds" % len(byte_text), msg_id, len(byte_text), byte_text)
def main(sock):
global file_name
print("connected succefuly. to run a command, write $<command> (no space)\nto request a file, enter file path.\nto exit this program enter exit.")
inputed_text = ''
while True:
inputed_text = input()
if inputed_text == '':
pass
elif inputed_text == "exit":
return
elif inputed_text[0] == "$":
sock.send(text_parse(inputed_text[1:], 0))
else:
file_name = inputed_text
sock.send(text_parse(inputed_text, 1))
def print_string(message, msg_len):
text = struct.unpack("%ds" % msg_len, message)[0].decode("utf-8")
sys.stdout.write(text)
sys.stdout.flush()
def copy_file(message):
global file_name
final_file = open(file_name, "wb")
final_file.write(message)
final_file.close()
def recieve_loop(sock):
while True:
try:
header = sock.recv(8)
if not header: break
msg_type = struct.unpack("I", header[:4])[0]
msg_len = struct.unpack("I", header[4:8])[0]
print(msg_type)
print(msg_len)
message = sock.recv(msg_len)
if msg_type == 2:
print_string(message, msg_len)
elif msg_type == 3:
copy_file(message)
except socket.timeout:
pass
if __name__ == "__main__":
print("welcome to remote desktop program.\nto connect to your computer, enter it's ip.\nto exit enter exit")
text_input = "b,kjhkf"
while True:
text_input = input()
if text_input == "exit":
exit()
else:
sock = try_to_connect(text_input)
if sock:
socket_recieve_thread = threading.Thread(target = recieve_loop, args = [sock])
socket_recieve_thread.start()
main(sock)
socket_recieve_thread.join()
else:
print("the computer is not online")

Python imports module but doesn't recognize it when i initiate it?

I honestly have no idea why this is happening, I assume due to it not being on stack-exchange it's a very n00by mistake on my part. so here's the error:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
UnboundLocalError: local variable 'socket' referenced before assignment
tcpServer.py
import socket
def Main():
UID = 1001
sockets = []
users = [] ## create usernames list
sessionLimit = input("session Queue Limit: ")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.1.74', 12127))
s.listen(sessionLimit) ## listen for 1 connection at a time
while True:
c, addr = s.accept()
sockets.append(c)
users.append(c.recv(1024).decode('utf-8'))
print("Connection from " + str(addr))
data = c.recv(1024).decode('utf-8') ## recieve 1024 bytes from client at a time, and then decode it into utf-8
if not data:
break
temp == data
temp.split(" ")
if temp[0] == "//": ## check to see if user has sent command
if temp[1] == "msg":
for i in range(len(users)):
if users[i] == temp[2]:
sockets[i].send((" ".join(temp[::2])).encode('utf-8'))
else: ## else, send data to all users. Could just use s.sendall(data.encode('utf-8'))
for socket in sockets:
socket.send(data.encode('utf-8')) ## send to sockets[socket]
##print("From connected user: " + data)
##data = data.upper()
##print("Sending: " + data)
##c.send(data.encode('utf-8'))
## command listening
commands = input("-> ")
commands.split(" ")
if commands[0] == "exit":
c.close() ## close connection
elif commands[0] == "/msg":
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send((" ".join(commands[::1])).encode('utf-8'))
"""
elif commands[0] == "/rename": ## dont implement yet, due to users[] length changing
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send("<server_" + UID + "> rename " + commands[2].encode('utf-8'))
"""
c.close()
if __name__ == "__main__":
Main()
Thanks for any help !
- Jacob
The issue is that you're using the variable name socket in the context of your Main() function when you do the following code block:
for socket in sockets:
socket.send(data.encode('utf-8')) ## send to sockets[socket]
That's causing an naming issue with the socket library. If you change that to:
for sock in sockets:
sock.send(data.encode('utf-8')) ## send to sockets[socket]
It will start to work. I also had to indent your code differently to ensure it was all in the Main() function you set up, and had to ensure the input() was parsed as an int. For reference, here's the full code block working for me:
import socket
def Main():
UID = 1001
sockets = []
users = [] ## create usernames list
sessionLimit = int(input("session Queue Limit: "))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.1.74', 12127))
s.listen(sessionLimit) ## listen for 1 connection at a time
while True:
c, addr = s.accept()
sockets.append(c)
users.append(c.recv(1024).decode('utf-8'))
print("Connection from " + str(addr))
data = c.recv(1024).decode('utf-8') ## recieve 1024 bytes from client at a time, and then decode it into utf-8
if not data:
break
temp == data
temp.split(" ")
if temp[0] == "//": ## check to see if user has sent command
if temp[1] == "msg":
for i in range(len(users)):
if users[i] == temp[2]:
sockets[i].send((" ".join(temp[::2])).encode('utf-8'))
else: ## else, send data to all users. Could just use s.sendall(data.encode('utf-8'))
for sock in sockets:
sock.send(data.encode('utf-8')) ## send to sockets[socket]
##print("From connected user: " + data)
##data = data.upper()
##print("Sending: " + data)
##c.send(data.encode('utf-8'))
## command listening
commands = input("-> ")
commands.split(" ")
if commands[0] == "exit":
c.close() ## close connection
elif commands[0] == "/msg":
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send((" ".join(commands[::1])).encode('utf-8'))
"""
elif commands[0] == "/rename": ## dont implement yet, due to users[] length changing
for i in range(len(users)):
if users[i] == commands[1]:
sockets[i].send("<server_" + UID + "> rename " + commands[2].encode('utf-8'))
"""
c.close()
if __name__ == "__main__":
Main()

Categories