I'm trying to create a message server type of thing. After connecting to the server client-side and attempting to type in a username, it gives the error:
"a bytes-like object is required, not 'str'"
And I wasn't sure If I was mishandling the encoding and decoding functions or not.
import socket, time, sys, threading
class Server:
def __init__(self, port):
while True:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.port = port
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(('127.0.0.1',port))
self.clients = []
self.usernames = []
print('Successfully bound socket!')
break
except:
print('Error binding, retrying....')
time.sleep(5)
def close(self):
self.socket.close()
def commands(self):
while True:
command = input()
if command.lower() in ['exit', 'end', 'quit', 'q']:
print('Closing Session.....')
server.close(), sys.exit()
def broadcast(self, message):
for client in self.clients:
client.send(message)
def handle(self, client):
while True:
try:
message = client.recv(1024)
server.broadcast(message)
except:
index = self.clients.index(client)
self.clients.remove(client)
client.close()
username = self.usernames[index]
server.broadcast(f'{username.decode("ascii")} has left!')
self.usernames.remove(username)
break
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username.encode("ascii")} has connected.')
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
def listen(self):
self.socket.listen(5)
print('Listening for new connections....')
while True:
client, addr = self.socket.accept()
client.settimeout(60)
server.receive(client, addr)
server = Server(4545)
try:
server.listen()
except:
server.close()
The problem occurs from the receive function:
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username.encode("ascii")} has connected.')
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
Have a look at this part of code :
def receive(self, client, addr):
while True:
#[...]
server.broadcast(f'{username.encode("ascii")} has connected.')
You're just encoding the username but not the complete string!
So it should be something like this :
#[...]
server.broadcast(f'{username} has connected.'.encode("ascii"))
#[...]
Here's the final working code:
import socket, time, sys, threading
class Server:
def __init__(self, port):
while True:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.port = port
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(('127.0.0.1',port))
self.clients = []
self.usernames = []
print('Successfully bound socket!')
break
except:
print('Error binding, retrying....')
time.sleep(5)
def close(self):
self.socket.close()
def commands(self):
while True:
command = input()
if command.lower() in ['exit', 'end', 'quit', 'q']:
print('Closing Session.....')
server.close(), sys.exit()
def broadcast(self, message):
for client in self.clients:
client.send(message)
def handle(self, client):
while True:
try:
message = client.recv(1024)
server.broadcast(message)
except:
index = self.clients.index(client)
self.clients.remove(client)
client.close()
username = self.usernames[index]
server.broadcast(f'{username.decode("ascii")} has left!')
self.usernames.remove(username)
break
def receive(self, client, addr):
while True:
print(f'New Socket Connection: {addr}')
try:
client.send('USERNAME: '.encode('ascii'))
username = client.recv(1024).decode('ascii')
self.usernames.append(username)
self.clients.append(client)
print(f'Username is: {username}')
server.broadcast(f'{username} has connected.'.encode("ascii"))
client.send('Connected to the server!'.encode('ascii'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
except Exception as e:
print(e)
print('Closed early! (Or wrong values entered!)')
socket.close()
print(f'Client {addr} closed.')
client.send()
def listen(self):
self.socket.listen(5)
print('Listening for new connections....')
while True:
client, addr = self.socket.accept()
client.settimeout(60)
server.receive(client, addr)
server = Server(4545)
try:
server.listen()
except:
server.close()
Related
So i am trying to make a message application with tkinter gui. I have a client and a server, which is currently just running locally.
So i i generate a fernet key which i first send to the server, so we can both encrypt with the same key (i know this probably should be encrypted when i send it).
The first time i call the client.connect() it works fine, gets the key and checks if the roomId exists. If it does not it spits out an error and all is fine. However if I try again, calling client.connect() the fernet key which the server receives gets all messed up.
First time
Client
b'Nwb0wki6ydmeZgEyMqo0ZFvvPm_grlpnYicjhCMZTMg='
b'Nwb0wki6ydmeZgEyMqo0ZFvvPm_grlpnYicjhCMZTMg='
b'Nwb0wki6ydmeZgEyMqo0ZFvvPm_grlpnYicjhCMZTMg='
Server
b'Nwb0wki6ydmeZgEyMqo0ZFvvPm_grlpnYicjhCMZTMg='
As you can see the first time it works fine
Second time
Client
b'tq2uBDFfpV0vAmDNpJKmA-87ElJqa5Unsme7OGCTG80='
b'tq2uBDFfpV0vAmDNpJKmA-87ElJqa5Unsme7OGCTG80='
b'tq2uBDFfpV0vAmDNpJKmA-87ElJqa5Unsme7OGCTG80='
Server
b'tq2uBDFfpV0vAmDNpJKmA-87ElJqa5Unsme7OGCTG80=gAAAAABfmnNNS9XplQlqNf3-7vlEgk-VAHsq6EIJaWTUhLyaCqIictM7v5rnh6_dMhKKNvGc3otMi08SEhtmgfyK3KSXD6SckOk9abFGW6-KS36b3jtThBdmid1EXxCmu7B0IgmulmZF_K0VhKAiOEty74nqZ_YLkDzfaaKHzXnPsfx-39ssKSA='
Even though i am calling the exact same method, and its making a new connecting, and it seems to be sending a perfectly fine key, the server recievieves something totally different. And yes i only have one client connected to the server
Client connection function
def connect(self, username="joe", roomId="12346", host="127.0.0.1", port="9001"):
self.host = host
self.port = int(port)
self.key = fernet.Fernet.generate_key()
print(self.key)
self.username = username
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((self.host, self.port))
self.connected = True
print(self.key)
self.sock.send(self.key)
print(self.key)
print("sendte key")
self.sock.sendall(Encryption().encryptMsg(self.username, self.key))
print("sendte username")
self.sock.sendall(Encryption().encryptMsg(roomId, self.key))
print(roomId)
print("sendte roomId")
msg = self.sock.recv(1024)
msg = Encryption().decryptMsg(msg, self.key)
print(msg)
if msg["msg"] == False:
self.disconnect()
return False
self.clientId, self.roomId = msg["msg"]
self.thread = threading.Thread(target=self.listen)
self.thread.start()
print("Started listening")
print(self.username, self.roomId, self.clientId)
return True
except Exception as e:
print(e)
self.disconnect()
return False
def disconnect(self):
print("lukker sock")
self.sock.shutdown(socket.SHUT_RDWR)
Server receiving function
def run(self):
self.sock.bind((self.host, self.port))
self.sock.listen(self.listenInt)
while True:
# try:
conn, addr = self.sock.accept()
print("Got connection from: ", addr)
newCon = threading.Thread(
target=self.handleConnection, args=(conn, addr))
newCon.start()
self.sock.close()
def handleConnection(self, conn, addr):
print("startet handler")
key = conn.recv(1024)
print("fikk key")
print(key)
username = Encryption().decryptMsg(conn.recv(1024), key)["msg"]
print("fikk username")
print(username)
roomId = int(Encryption().decryptMsg(conn.recv(1024), key)["msg"])
print("fikk roomid")
print(roomId)
print(self.rooms)
if roomId == 0:
room = Room(self)
roomId = room.roomId
self.rooms[roomId] = room
print("lagde rom")
elif roomId not in self.rooms:
print("finner ikke rom")
conn.sendall(Encryption().encryptMsg(False, key))
print("sendte false")
conn.close()
return
room = self.rooms[roomId]
newCon = threading.Thread(
target=serverConnection, args=(conn, addr, key, room, username))
newCon.start()
I am trying to build a Python program that will pass a message between a Client and Server. The idea is to pass one message from the Server and have the Client modify it and pass it back to the Server.
Right now I am suck on trying to get the Client's message back to the Server; the message 'Congrats! You have connected' is converted to uppercase,
Server
import socket
class Server:
def __init__(self, host, port):
self.serverSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.host = host
self.port = port
def bind(self):
self.serverSocket.bind((self.host, self.port))
self.serverSocket.listen(5)
def run(self):
while True:
print ('Waiting for a connection')
(clientSocket, addr) = self.serverSocket.accept()
print ('Got a connection from {}'.format(str(addr)))
message = 'Congrats! You have connected'
self.sendMessage(message, clientSocket)
self.recieveMessage()
clientSocket.close()
def sendMessage(self, message, clientSocket):
clientSocket.send(message.encode('ascii'))
def recieveMessage(self):
(clientSocket, addr) = self.serverSocket.accept()
message = self.serverSocket.recv(1024).decode('ascii')
print(message)
def closeSocket(self):
self.serverSocket.close()
if __name__ == '__main__':
myServer = Server('127.0.0.1', 5555)
myServer.bind()
myServer.run()
myServer.recieveMessage()
myServer.closeSocket()
Client
import socket
class Client:
def __init__(self, host, port):
self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.host = host
self.port = port
def connect(self):
self.serverSocket.connect((self.host, self.port))
def getMessage(self):
return self.serverSocket.recv(1024).decode('ascii')
def modifyMessage(self):
return message.upper()
def sendMessage(self, upperCaseMessage, server):
(server, addr) = self.serverSocket.accept()
serverSocket.send(upperCaseMessage.encode('ascii'))
def closeConnection(self):
self.serverSocket.close()
if __name__ == '__main__':
myClient = Client('127.0.0.1', 5555)
myClient.connect()
message = myClient.getMessage()
upperCaseMessage = myClient.modifyMessage()
myClient.sendMessage(upperCaseMessage, serverSocket)
myClient.closeConnection()
The issue is the following.
I have the following server:
import socket
class Receiver:
TCP_IP = '127.0.0.1'
TCP_PORT = 2999
BUFFER_SIZE = 20
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)
conn, addr = s.accept()
print('Connection address:', addr)
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print("received data:", data)
conn.send('0x55'.encode()) # echo
conn.close()
And the client:
import socket import logging
class NvgClient:
_instance = None
def __init__(self):
self.s = socket.socket()
self.s.settimeout(3)
self.connect()
return
def __del__(self):
try:
self.s.close()
finally:
return
#staticmethod
def getInstance():
if(NvgClient._instance == None):
NvgClient._instance = NvgClient()
return NvgClient._instance
def connect(self):
try:
print("****** TRYING_TO_CONNECT_TO_SOCKET ********")
self.s.connect(('127.0.0.0', 2999))
except socket.error:
self.s.close()
self.s = socket.socket()
self.s.settimeout(3)
self.connect()
logging.error("Socket can`t connect! Reconnected.")
return
def send(self, data: bytearray):
try:
print("****** TRYING_TO_SEND_DATA ********")
self.s.send(data)
logging.info(str(data))
rdata = self.s.recv(1024)
if(rdata[0] == 0x55 and rdata[1:5] == data[0:4]):
logging.info('NVG OK')
return True
else:
logging.info('NVG BAD')
except socket.timeout:
self.s.close()
self.connect()
except IndexError:
logging.info('Server returns nothing. Reconnecting.')
self.s.close()
self.s = socket.socket()
self.s.settimeout(3)
self.connect()
return False
But when I try to send some data, it is impossible to connect to server:
self.s.connect(('127.0.0.0', 2999)). I get socket.error.
Is there any mistakes or something wrong in code? For other simple examples or telnet, server works well.
You need to connect to localhost which is:
127.0.0.1
and not
127.0.0.0
as you wrote for your client (server is okay though)
I have set up a socket server with a client and a host.
It works fine until the client has disconnected, with both .shutdown() and .close().
When I then launch the client again, it can't connect.
I presume this is not because of how I've written my code but rather what I haven't written.
How do I make the server truly disconnect the client's connection so that it can connect again?
Server:
import socket, threading, time, json
ONLINE_USERS = []
SESSION = None
class User():
def __init__(user, connection, address):
print('for', address, '{Connection established}')
user.connection = connection
user.address = address
user.character = None
threading.Thread(target=user.process, args=(), daemon=True).start()
def process(user):
time.sleep(1)
user.send("&pLogin\n^^^^^\n")
username = user.send("&iUser>")
password = user.send("&iPass>")
print(user.ping())
print(user.logout())
def send(user, *x):
user.connection.sendall(str.encode(str(x)))
data = user.connection.recv(1024)
return data if data!=b'\x01' else True
def recv(user, x):
user.connection.recv(x)
def ping(user):
start = time.time()
user.connection.sendall(b'\x02')
end = float(user.connection.recv(1024))
return round((end - start) * 1000)
def logout(user):
user.connection.sendall(b'\x04')
return user.connection.recv(4)
class Session():
def __init__(session, host='', port=12345):
session.host = host
session.port = port
session.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
session.socket.bind((host, port))
session.socket.listen(10)
def accept():
conn = User(*session.socket.accept())
session.thread_accept = threading.Thread(target=accept, args=(), daemon=True).start()
def shutdown():
for user in ONLINE_USERS.keys():
ONLINE_USERS[user].connection.sendall(bytes([0xF]))
if __name__ == '__main__':
SESSION = Session()
input('Press heart to continue!\n')
Client:
import socket, sys, threading, time, os
def clear(t=0.5):
time.sleep(t)
os.system('cls')
def tryeval(x, default):
try:
return eval(x)
except:
return default
class Client():
def __init__(client):
try:
server_info = input('IP_ADDRESS:PORT>').split(':')
client.host = server_info[0]
client.port = int(server_info[1])
except:
client.host = 'localhost'
client.port = 12345
client.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.socket.settimeout(10)
try:
client.socket.connect((client.host, client.port))
clear()
client.data_exchange()
finally:
client.shutdown()
def data_exchange(client):
while True:
data = client.socket.recv(1024)
if data:
if data==b'\x02':
client.socket.sendall(str.encode(str(time.time())))
elif data==b'\x04':
client.shutdown()
else:
data = tryeval(data, ())
response = []
for item in data:
try:
prefix, content = item[:2], item[2:]
if prefix=='&p':
print(content, end='')
elif prefix=='&i':
response.append(input(content))
if prefix=='&c':
time.sleep(float(content))
clear()
except:
pass
if len(response)>0:
client.socket.sendall(str.encode(str(tuple(response))))
else:
client.socket.sendall(b'\x01')
time.sleep(0.001)
def shutdown(client):
try:
client.socket.sendall(b'\x04')
except:
pass
print('Shutting down program.')
client.socket.shutdown(socket.SHUT_RDWR)
print('Socket has been shutdown.')
client.socket.close()
print('Socket has been closed.')
print('Exiting program')
time.sleep(1)
sys.exit()
if __name__ == '__main__':
client = Client()
"The server repeatedly calls accept waiting for new incoming connections." No it doesn't. It calls accept once in a thread...which exits. – Mark Tolonen
self.handlers.append(ConnHandler(sock, self.handlers))I'm new to python and I tried to write a simple socket server to test stuff out and get to know the language better.
import asyncore
import socket
import json
class ConnHandler(asyncore.dispatcher_with_send):
def __init__(self, conn, handlerlist):
asyncore.dispatcher_with_send.__init__(self, conn)
self.handlers = handlerlist
def handle_close(self):
self.close()
print 'Socket closed'
if(self.handlers.count(self) > 0):
self.handlers.remove(self);
def handle_read(self):
data = ''
more = True
while more:
try:
data += self.recv(1024)
except socket.error, e:
more = False
if data == '':
return
try:
message = json.loads(data)
except ValueError:
self.send('Invalid JSON\n')
return
print message
class TestServer(asyncore.dispatcher):
def __init__(self, host, port):
asyncore.dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind((host, port))
self.listen(5)
self.handlers = []
def handle_accept(self):
pair = self.accept()
if pair is not None:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
self.handlers.append(ConnHandler(sock, self.handlers))
def sendToAll(self, string):
for h in self.handlers:
h.send(string + '\n')
server = TestServer('localhost', 55555)
asyncore.loop()
My problem is the following.
If I connect to the server with telnet and then quit telnet to close the connection, python just spams 'Socket closed' in the terminal. How can I fix this? Are there obvious beginner mistakes in the above code?
handle_close is not meant to detect if peer is disconnected, you get this information in handle_read if .recv call returns an empty string. Then you can close the socket, and then handle_close is called.
Here is a modified version of your code:
def handle_close(self):
print 'Socket closed'
if(self.handlers.count(self) > 0):
self.handlers.remove(self);
def handle_read(self):
data = ''
more = True
while more:
try:
new_data = self.recv(1024)
if not new_data:
self.close()
return
else:
data += new_data
except socket.error, e:
more = False
if data == '':
return
try:
message = json.loads(data)
except ValueError:
self.send('Invalid JSON\n')
return
print message