Python chat application - multithreading

I am trying to write a simple chat server, that takes message from 1 user and sends to all other users. The other users can simultaneously send messages and receive them.
On client side one thread continuously waits for messages and other thread sends messages.
import socket
import threading
def getMessage(s):
while True:
s.send(raw_input("Message: "))
#Main
port = 1041
host = 'localhost'
s = socket.socket()
s.connect((host, port))
background_thread = threading.Thread(target=getMessage, args=(s,))
background_thread.daemon = True
background_thread.start()
while True:
print s.recv(1024)
On server side the server, takes the incoming connection request, opens a new thread for each new request and waits for their messages, when a connection sends a message, the server broadcasts it to all other connections that are open.
import socket
from thread import *
def ClientThread(connection, clients):
while True:
message = connection.recv(1024)
connection.send("Ack\n")
broadcast(connection, clients, message)
def broadcast(connection, clients, message):
for conn in clients:
if(conn != connection):
conn.send(message)
def AcceptConnections(clients):
while True:
connection, address = s.accept()
print "Got connection from ",connection
clients.append(connection)
start_new_thread(ClientThread, (connection, clients))
#Main
print "Started server"
port = 1041
host = 'localhost'
s = socket.socket()
s.bind((host, port))
s.listen(5)
clients = []
AcceptConnections(clients)
Expected: When one client sends a message, all other connected clients receive that message, irrespective of them typing and sending a message.
Reality: Other clients receive the message only after they send 1 or 2 messages.

Related

Can't receive multiple messages on server using TCP socket (Python)

I am new to sockets and don't really know how to receive multiple messages from the same client. I only receive the first message and not the rest.
Server code:
import socket
IP = "127.0.0.1"
PORT = 65432
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((IP, PORT))
server.listen()
while True:
communication_socket, address = server.accept()
msg = communication_socket.recv(1024).decode("utf-8")
print(msg)
Client code:
import socket
import time
HOST = "127.0.0.1"
PORT = 65432
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST, PORT))
socket.send("success".encode("utf-8"))
time.sleep(2)
socket.send("?".encode("utf-8"))
socket.close()
communication_socket, address = server.accept()
msg = communication_socket.recv(1024).decode("utf-8")
The current code accepts the new connection and then does a single recv. That's why it gets only the first data. What you need are multiple recv here after the accept.
... multiple messages from the same client
TCP has no concept of messages. It is only a byte stream. There is no guaranteed 1:1 relation between send and recv, even if it might look like this in many situations. Thus message semantics must be an explicit part of the application protocol, like delimiting messages with new lines, having only fixed size messages or similar.

How to initiate a socket connection from server to client?

I have setup a tcp socket between a client and a server, very basic. Client side:
#!/usr/bin/env python3
import socket
# create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = "81.88.95.250"
port = 25000
# connection to hostname on the port.
s.connect((host, port))
# Receive no more than 1024 bytes
msg = s.recv(1024)
s.close()
print (msg.decode('ascii'))
server side:
#!/usr/bin/env python3
import socket
# create a socket object
serversocket = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
port = 25000
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
while True:
# establish a connection
clientsocket,addr = serversocket.accept()
print("Got a connection from %s" % str(addr))
msg = 'Thank you for connecting'+ "\r\n"
clientsocket.send(msg.encode('ascii'))
clientsocket.close()
My target is to send notification from client to server, and that's easy. The difficult part is that I also need in some circumstances to start the connection from the server and to send a command to the client and this must be executed as soon as it is received, so I cannot setup a periodic "poll". But I'm quite confused on this part, because the client is behind a NAT, not exposed with a public IP.

I'm trying to make chat program using Python 3.6 but I think I can't retain connection

import socket
host = 'address' # as you know this isn't letters but I just write it as address for now.
port = 50000
bufsize = 1024
server = socket.socket()
server.bind((host, port))
server.listen(5)
while 1:
print("Waiting Connection")
client, address = server.accept()
print("Connected")
welcomemsg = ("send messages")
client.send(bytes(welcomemsg, "utf-8"))
print("client info")
print(address)
msgfromclient = server.recv(bufsize).decode("utf8")
client.send(bytes(msgfromclient, "utf-8"))
import socket
bufsize = 1024
client = socket.socket()
while 1:
client.connect(('address', 50000))
welcomemsg = client.recv(bufsize).decode("utf8")
print(welcomemsg)
msgtoserver = input()
server.send(bytes(msgtoserver, "utf-8"))
msgfromserver = client.recv(bufsize).decode("utf8")
print(msgfromserver)
I think I can connect server and client and then I can make server send a welcome message to client and client can receive that message.
But after that I think I can't retain connection between server and client any longer.
I want to make server and client retain connection after server send a welcome message to client and client send a message to server and then server send it again to all the clients (yes I am trying to make chat program.)
I am using Windows.

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)

Why doesn'e send() function return 0 in this situation?

i wrote a sample of socket,both server and client program.At server,when it accept the connection,it will close it at once.At client ,it will connect to server,then sleep for 1 secs,and then send something to server.
What confuse me is why send function doesn't return 0 ?The code is below
Client.py
import socket
import time
clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
clientsocket.connect(("127.0.0.1",8886))
ret = clientsocket.send(("Hello world").encode('utf-8'))
time.sleep(1.0)
print("All send bytes is {}".format(ret))
except socket.error as msg:
print(msg)
Server.py
import socket
serversocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serversocket.bind(("127.0.0.1",8886))
serversocket.listen(5)
while True:
clientsocket,addr = serversocket.accept()
clientsocket.shutdown(2)
clientsocket.close()
Send function return 11 not 0.after connection established,i close it immediately.but client sends data successfully.that confuses me

Resources