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)
Related
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()
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()
I'm trying to build a socket and I want to print an object of clients, but for some reason whenever I connect it just returns empty {}
I'm new to Python and would like some insight
import socket
from threading import Thread
from multiprocessing import Process
import time as t
previousTime = t.time()
clients = {}
hostAddr = "127.0.0.1"
hostPort = 80
class sClient(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.sock = socket
self.addr = address
self.start()
def run(self):
print("\nClient Connected from {}!".format(self.addr[0]))
self.sock.sendall("Welcome master".encode())
class sHost():
def __init__(self, host, port, clients):
self.sHost = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sHost.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sHost.bind((host, port))
self.sHost.listen()
self.start_listening()
def start_listening(self):
while 1:
clientSocket, clientAddr = self.sHost.accept()
clients[clientSocket.fileno()] = clientSocket
sClient(clientSocket, clientAddr)
def SendMsgToAllClients(msg):
print(clients) # this is empty
for client in clients.values():
try:
client.sendall(msg.encode())
except Exception as e:
print("Client probably disconnected, removing...")
finally:
del clients[client.fileno()]
if __name__ == '__main__':
Process(target=sHost, args=(hostAddr, hostPort, clients)).start()
print("Server is running")
while 1:
if previousTime + 3 <= t.time():
SendMsgToAllClients("Test")
previousTime = t.time()
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
I'm having problems detecting a broken socket when a broken pipe exception occurs. See the below code for an example:
The Server:
import errno, select, socket, time, SocketServer
class MetaServer(object):
def __init__(self):
self.server = Server(None, Handler, bind_and_activate=False)
def run(self, sock, addr):
rfile = sock.makefile('rb', 1)
self.server.process_request(sock, addr)
while 1:
r, _, _ = select.select([rfile], [], [], 1.0)
if r:
print 'Got %s' % rfile.readline()
else:
print 'nothing to read'
class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
allow_reuse_address = True
daemon_threads = True
class Handler(SocketServer.StreamRequestHandler):
def handle(self):
print 'connected!'
try:
while 1:
self.wfile.write('testing...')
time.sleep(1)
except socket.error as e:
if e.errno == errno.EPIPE:
print 'Broken pipe!'
self.finish()
self.request.close()
if __name__ == '__main__':
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 8081))
s.listen(5)
ms = MetaServer()
while 1:
client, address = s.accept()
ms.run(client, address)
The Client:
import select, socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 8081))
while 1:
r, _, _ = select.select([s], [], [], 1.0)
if not r:
continue
msg = s.recv(1024)
print 'Got %s' % (msg,)
Now, if I run the server and client, all is well, and I get a "nothing is read" message every second. As soon as I CTRL-C out of the client, the server goes crazy and starts to "read" from what should be a busted socket, dumping a lot of "Got " messages.
Is there some way to detect this broken socket in the MetaServer.run() function to avoid the above said behavior?
Yes, that's something which is not really in the documentation but old Un*x behavior: You need to abort when you get an empty string.