How does my server know that a client has disconnected? - python-3.x

So i have a TCP connection with a select, to handle multiple clients.
These multiple clients chat between each other having a UDP connection independent of the server.
The server keeps a list with all connected clients and notifies each one of them when a new client arrives or when one disconnects.
I have a working code.
I do not understand how, where in the code of the client, does it send the disconnection information to the server. Because the server receives the information that a client disconnects. BUT HOW
server.py:
import pickle
import select
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
address = ('0.0.0.0', 7000)
server.bind(address)
print('Starting up on %s port %s' % address)
input_sockets = [server]
output_sockets = []
clients = []
server.listen(10)
i = 0
while True:
readable, writable, exceptional = select.select(input_sockets, output_sockets, input_sockets)
for s in readable:
if s is server:
i = i+1
client_socket, client_address = s.accept()
print('New connection from client ' + str(i) + ' with address: ' + str(client_address))
client_socket.send(pickle.dumps(clients))
for client in input_sockets:
if client is not server:
client.send(pickle.dumps(client_address))
input_sockets.append(client_socket)
clients.append(client_address)
else:
client_address = s.getpeername()
print("Client with address '" + str(client_address) + "' disconnected")
clients.remove(client_address)
input_sockets.remove(s)
for client in input_sockets:
if client is not server:
client.send(pickle.dumps(client_address))
s.close()
client.py
import socket
import pickle
import threading
import select
def chat(udp_sock):
global done
while not done:
message = input()
if message == "QUIT":
done = True
else:
for client in clients:
udp_sock.sendto(message.encode('utf-8'), client)
done = False
server_address = ('127.0.0.1', 7000)
s_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s_tcp.connect(server_address)
clients_data = s_tcp.recv(1024)
clients = pickle.loads(clients_data)
s_udp.bind(s_tcp.getsockname())
reading = threading.Thread(target=chat, args=(s_udp,))
reading.start()
while not done:
r, w, e = select.select([s_tcp, s_udp], [], [], 1)
for s in r:
if s == s_tcp:
addr = s_tcp.recv(1024)
addr = pickle.loads(addr)
if addr in clients:
clients.remove(addr)
print("Client " + str(addr) + " has disconnected.")
else:
clients.append(addr)
print("Client " + str(addr) + " is now connected.")
if s == s_udp:
msg, addr = s_udp.recvfrom(1024)
msg = msg.decode()
print("[" + str(addr) + "]: " + str(msg))
reading.join()
s_tcp.close()
s_udp.close()
enter code here

for s in readable:
if s is server:
...
else:
client_address = s.getpeername()
print("Client with address '" + str(client_address) + "' disconnected")
clients.remove(client_address)
input_sockets.remove(s)
The server simply disconnects a client when select shows that it could read from the client socket. Since the client never sends anything to the server on the TCP connection, the only case where the client socket is readable is when the client disconnects. In this case a recv on the client socket would return '', i.e. no data as a sign that the socket has been disconnected. T
The client thus just needs to disconnect the TCP connection in order to signal to the server that the client is done. This is explicitly done in the code by closing the socket, but would also be implicitly done when the client exits.
s_tcp.close()

Related

Trouble getting my server to respond back to client | Python | Sockets

I'm trying to repurpose this script, I want the server to send messages to my client, and I want the client to be the one that 'reaches out' and makes the connection. As you can see, with the script I have, the client is the one reaching out but it's the one that can send the messages to the server. I've tried looking at other scripts, moving the send and handle function around, but I feel like my inexperience with sockets got me stumped. Any help would be appreicated.
Server:
import socket
import threading
HEADER = 64
PORT = 5430
SERVER = '192.110.100.189' # socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
# defines the type of connection
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
def handle_client(conn, addr):
print(f'[NEW CONNECTIONS] {addr} connected')
connected = True
while connected:
# the header variable here acts as a protocol to give us an idea of how many bytes are being sent
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg == DISCONNECT_MESSAGE:
break
print(f'{addr} | {msg}')
conn.send('msg recieved'.encode(FORMAT))
conn.close()
def start():
server.listen()
print(f'[LISTENING] Server is listening on {SERVER}')
while True:
conn, addr = server.accept()
thread = threading.Thread(target = handle_client, args = (conn, addr))
thread.start()
print(f'[ACTIVE CONNECTIONS] {threading.activeCount() - 1}')
print('[STARTNG] Server is starting')
start()
Client:
import socket
HEADER = 64
PORT = 5430
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = '!END'
SERVER = '192.110.100.189'
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
while True:
enter = input('CLIENT - ')
send(enter)
if enter == DISCONNECT_MESSAGE:
break

Socket chat app Freezing when sending a message

Hi I was following a tech with Tim tutorial about sockets and I am building a chat app and I am trying to create a dictionary with the names and the IP in it. but when I connect and type my name the client-side app freezes but I don't know why so can you see if you can help me this is the code.
Server-side code
import socket
import threading
import io
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "dis"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
Names = {}
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg.split(':::')[0] == 'Name':
name = msg.split(':::')[-1]
Names[addr] = name
print(Names.get(addr))
elif msg == DISCONNECT_MESSAGE:
connected = False
print(f'[{addr}] Has disconnected')
# Names.pop(addr)
else:
conn.send('message recieved'.encode(FORMAT))
print(msg)
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
print("[STARTING] server is starting...")
start()
And this is the client-side code
import socket
HEADER = 64
PORT = 5050
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "dis"
SERVER = '127.0.1.1'
print(SERVER)
Name = input('Enter your name: ')
ADDR = (SERVER, PORT)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(ADDR)
def send(msg):
message = msg.encode(FORMAT)
msg_length = len(message)
send_length = str(msg_length).encode(FORMAT)
send_length += b' ' * (HEADER - len(send_length))
client.send(send_length)
client.send(message)
print(client.recv(2048).decode(FORMAT))
send('Name:::' + Name)
while True:
msg = input('what message do you want to send type dis to disconnect: ')
if msg != DISCONNECT_MESSAGE :
send(msg)
elif msg == DISCONNECT_MESSAGE:
send(msg)
break
elif msg == None:
print("please type a message and don't leave it a blank")
In your client code, under function send(msg) you are expecting response from server once the client sent a message, and you are using the same function for sending username as well.
In the server you have not coded to respond for username.
Hence your client is actually waiting for response from server, for the username it just sent. That's why it looks frozen.
Adding a response like Hello username in server will resolve this.
Server
import socket
import threading
import io
HEADER = 64
PORT = 5050
SERVER = socket.gethostbyname(socket.gethostname())
ADDR = (SERVER, PORT)
FORMAT = 'utf-8'
DISCONNECT_MESSAGE = "dis"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
Names = {}
def handle_client(conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
msg_length = conn.recv(HEADER).decode(FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(FORMAT)
if msg.split(':::')[0] == 'Name':
name = msg.split(':::')[-1]
Names[addr] = name
print(Names.get(addr))
conn.send(f'Hello {name}'.encode(FORMAT))
elif msg == DISCONNECT_MESSAGE:
connected = False
print(f'[{addr}] Has disconnected')
# Names.pop(addr)
else:
conn.send('message recieved'.encode(FORMAT))
print(msg)
conn.close()
def start():
server.listen()
print(f"[LISTENING] Server is listening on {SERVER}")
while True:
conn, addr = server.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
print("[STARTING] server is starting...")
start()

Connection error between server client OS error

Hello I am pretty much new to socket and I was trying to make a connection inside my local computer using socket.
this is the server
import socket
def server():
host = socket.gethostname() # get local machine name
port = 8080 # Make sure it's within the > 1024 $$ <65535 range
s = socket.socket()
s.bind(('192.168.56.1', port))
s.listen(1)
client_socket, adress = s.accept()
print("Connection from: " + str(adress))
while True:
data = s.recv(1024).decode('utf-8')
if not data:
breakpoint
print('From online user: ' + data)
data = data.upper()
s.send(data.encode('utf-8'))
s.close()
if __name__ == '__main__':
server()
and this is the client
import socket
def client():
host = socket.gethostname() # get local machine name
port = 8080 # Make sure it's within the > 1024 $$ <65535 range
s = socket.socket()
s.connect(("192.168.56.1", port))
message = input('-> ')
while message != 'q':
s.send(message.encode('utf-8'))
data = s.recv(1024).decode('utf-8')
print('Received from server: ' + data)
message = input('==> ')
s.close()
if __name__ == '__main__':
client()
I know there are useless lines in there but I will clean it up after I finish my connection .

can't send data from react-native app to python server

I'm doing an application that send and recieve data with python socket server. The application written with react-native. Everytime i connect and try send/recieve data it give that error: GET /socket.io/?EIO=3&transport=polling&t=Mlquqm0 HTTP/1.1
actually ı send a data like "hello server" but server recieve that error.
python socket working in a ubuntu server. i tried this on a python client and it's work but not react-native client.
server.py:
import socket
import sys
import ast
import os
import time
HOST = ip
PORT = port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# socket.socket: must use to create a socket.
# socket.AF_INET: Address Format, Internet = IP Addresses.
# socket.SOCK_STREAM: two-way, connection-based byte streams.
print('socket created')
# Bind socket to Host and Port
try:
s.bind((HOST, PORT))
except socket.error as err:
print
'Bind Failed, Error Code: ' + str(err[0]) + ', Message: ' + err[1]
sys.exit()
print('Socket Bind Success!')
# listen(): This method sets up and start TCP listener.
s.listen(10)
print('Socket is now listening')
while 1:
conn, addr = s.accept()
print('Connect with ' + addr[0] + ':' + str(addr[1]))
buf = conn.recv(64)
buf = buf.decode()
command = str(buf)
print(command)
nickname,password,command = command.split()
gazoz = str(nickname) + " " + str(password) + " " + str(command)
input = open("input.txt","a+",encoding="utf-8")
input.write(str(gazoz) + "\n")
input.close()
print(nickname)
time.sleep(2)
if os.path.isfile("connection/us_" + nickname + ".txt"):
data = open("connection/us_" + nickname + ".txt","r",encoding="utf-8")
msg = data.read()
print(msg)
data.close()
os.remove("connection/us_" + nickname + ".txt")
msg = str.encode(msg)
if len(msg) == 0:
msg = "pek bisi yok"
msg = str.encode(msg)
conn.send(msg)
s.close()
react native client
import io from 'socket.io-client';
const socket = io("ip:port");
socket.connect();
socket.emit("hello server");
socket.close();
can you try this ?
import SocketIOClient from "socket.io-client/dist/socket.io";
const socket = await SocketIOClient(url);
socket.on("connect", () => { console.log("connected") });

python3: two clients sending data to server using sockets

I'm working with 3 raspberry pi, one as a server and the two others are clients. What I want to do is to make the clients communicate with the server simultaneously, I don't want to wait for client1 communication to be done in order to launch client2 request to the server (which I succeeded to do). However, I want each client to send different data to server at the same time. I tried to use Sockets and threading, like below.
server code:
import socket
import RPi.GPIO as GPIO
from threading import Thread
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[+] New server socket thread started for " + ip + ":" + str(port))
def run(self):
while True :
data = conn.recv(2048)
data = data.decode('utf-8')
print ("Server received data:", data)
MESSAGE = input("Multithreaded Python server : Enter Response from Server/Enter exit:")
if MESSAGE == 'exit':
break
conn.send(str.encode(MESSAGE)) # echo
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = ''
TCP_PORT = 9050
BUFFER_SIZE = 2000 # Usually 1024, but we need quick response
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(2)
threads = []
list_data=[]
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048)
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)
for t in threads:
t.join()
client1 code:
import socket
import RPi.GPIO as GPIO
import time
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient1: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client2 received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
client2 code:
import socket
import RPi.GPIO as GPIO
import time
import socket
host = '192.168.0.198'
port = 9050
BUFFER_SIZE = 2000
MESSAGE = input("tcpClient2: Enter message/ Enter exit:")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
while MESSAGE != 'exit':
s.send(str.encode(MESSAGE))
data = s.recv(BUFFER_SIZE)
data = data.decode('utf-8')
print (" Client received data:", data)
MESSAGE = input("tcpClient2: Enter message to continue/ Enter exit:")
when i run, i obtain:
in the server terminal:
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.197:47012
Multithreaded Python server : Waiting for connections from TCP clients...
[+] New server socket thread started for 192.168.0.196:47886
Multithreaded Python server : Waiting for connections from TCP clients...
in client1 terminal:
tcpClient1: Enter message/ Enter exit:begin
in client2 terminal:
tcpClient2: Enter message/ Enter exit:begin
It seems like server didn't receive or send any data.
As #Hikke mentioned in his comment, your server receives at two different places. The conn.recv call in this code snippet eats up the data that the server receiving thread is expecting. Remove data = conn.recv(2048) in your server's main loop:
while True:
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = s.accept()
data = conn.recv(2048) # <== dont eat the data of your thread here!
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
list_data.append(data)

Resources