Socket Messaging Client/Server: Client not sending message - python

I am trying to create a simple chat program using Python and Socket. The server handles the connection between two clients. Whenever I run the program, for one of the clients, every message after the first one does not send. The message does not even reach the server.
This is on Windows, Python3. I've integrated threading so messages can be sent and received at the same time; however, the problem persists.
Server.py
conns = [] # list that stores both connections
def accept(sk):
while True:
conn, addr = sk.accept()
conns.append(conn)
print(addr, "has connected")
t = threading.Thread(target=accept, args=(sk,))
t.start() #start accept thread
def send(conn):
while True:
message = conn.recv(2048)
print(message)
for conn in conns:
conn.send(message) #sends message to every connection
print("Sent message")
t = threading.Thread(target=send, args=(conn,))
t.start() #start threading for send
Client.py
def recvMessages(s):
while True:
message = s.recv(2048)
print(message)
message = message.decode()
messages.append(message)
os.system("cls")
for message in messages:
print(message)
def sendMessage(s):
while True:
message = input()
message = message.encode()
s.send(message)
s = socket.socket()
host = socket.gethostname()
port = 8080
s.connect((host, port))
messages = []
print("Connected")
connected = True
threading.Thread(target=sendMessage, args=(s,)).start()
threading.Thread(target=recvMessages, args=(s,)).start()
All the messages should be sent from both clients, but one client can never send multiple messages, the other works fine.

Your server code is missing it's socket, and accept is not being run in your example, you also have invalid indentation as James pointed out, next time provide a minimal reproducible example.
I also cleaned up your files a bit, as you followed some bad practice, specifically with broadcasting the messages to all clients "def send" which actually receives, avoid confusing naming :)
in your server code you also sent only to one connection (which in your example doesn't exist) which it should be running the receive and send each time a new message is received
server.py
import socket
import threading
conns = [] # list that stores both connections
def accept(sk):
while True:
conn, addr = sk.accept()
conns.append(conn)
print(addr, "has connected")
# receive from new client
receive_t = threading.Thread(target=receive, args=(conn,))
receive_t.start() # start threading for send
def send(s, msg):
# change message ..
s.send(msg)
def broadcast(msg):
for conn in conns:
send(conn, msg)
def receive(conn):
try:
while True:
message = conn.recv(2048)
if not message: # detects if socket is dead, by testing message
print("client sent Nothing, removing")
conns.remove(conn)
break
broadcast(message) # send to all clients
except ConnectionResetError as e:
print('Could not send must be disconnected ')
conns.remove(conn) # remove dead socket
# added missing socket
sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen(1) # needs to bind and listen
t = threading.Thread(target=accept, args=(sock,))
t.start() # start accept thread
client.py
import os
import socket
import threading
messages = []
def recvMessages(s):
while True:
message = s.recv(2048)
message = message.decode()
print('new message= ', message)
messages.append(message)
os.system("cls")
for message in messages:
print(message)
def send_message(s):
while True:
message = input()
message = message.encode()
s.send(message)
s = socket.socket()
host = '127.0.0.1'
port = 8080
s.connect((host, port))
print("Connected")
connected = True
# added missing receive
receive = threading.Thread(target=recvMessages, args=(s,)) # missed receive thread in example
receive.start()
send_message(s)

Related

How to send a chatlog of all written chats to a newly joined client using socket programming in Python?

I have written a simple server and client py using UDP. The base is working, however I want that every time a user (client) joins, he would receive a chatlog of everything that has been said.
This is my code until now:
Server:
import socket
import threading
import queue
import pickle
messages = queue.Queue()
clients = []
# AF_INET used for IPv4
# SOCK_DGRAM used for UDP protocol
ip = "localhost"
port = 5555
chatlog=[]
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# binding IP and port
UDPServerSocket.bind((ip, port))
def receive():
while True:
try:
message, addr = UDPServerSocket.recvfrom(1024)
messages.put((message, addr))
chatlog.append((message,addr))
except:
pass
def broadcast():
while True:
while not messages.empty():
message, addr = messages.get()
print(message.decode())
if addr not in clients:
clients.append(addr)
for client in clients:
try:
if message.decode().startswith("SIGNUP_TAG:"):
name = message.decode()[message.decode().index(":") + 1:]
UDPServerSocket.sendto(f"{name} joined!".encode(), client)
if len(chatlog)>0:
sending= pickle.dumps(chatlog)
UDPServerSocket.sendto(sending, client)
else:
pass
else:
UDPServerSocket.sendto(message, client)
except:
clients.remove(client)
t1 = threading.Thread(target=receive)
t2 = threading.Thread(target=broadcast)
t1.start()
t2.start()
And the client
import socket
import threading
import random
client= socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client.bind(("localhost", random.randint(7000, 8000))) # random port for every client
name = "Henk" #test name
def receive():
while True:
try:
message, _ = client.recvfrom(1024)
print(message.decode())
except:
pass
t= threading.Thread(target= receive)
t.start()
#this gives the server the name of the people who have entered the server
client.sendto(f"SIGNUP_TAG: {name}".encode(), ("localhost", 5555))
while True:
message= input("")
if message=="!q":
exit()
else:
client.sendto(f'[{name}]: {message}'.encode(), ("localhost",5555))
So I am actually a bit stuck on how I will approach this. Shall create a text file where every time that a message is written it gets written on the file as well? Or shall I create some kind of string list/database where every message is stored :/

Python socket problem-ConnectionRefusedError: [WinError 10061]

I wanted to create a server-client chatbox room in python, where multiple clients could send messages in the chat box.
This is the server code
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
and this is the client code
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
write_thread = threading.Thread(target = write)
write_thread.start()
However, whenever i inputted the nickname in the command prompt there was an error
Traceback (most recent call last):
File "C:\Users\march\Documents\Programming\Pyhton\client.py", line 8, in <module>
client.connect(('127.0.0.1', 9879))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
I wonder what's the problem because the port for both server and client are the same and the port is available.
On your server code you're missing a call to the receive function that runs the while loop and puts the server on accept for connections.
The code becomes
import threading
import socket
#setting up the local host and the local port
host = '127.0.0.1'
port = 9879
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port)) #hosting the server to the host
server.listen() #server listen to incoming connection
#list for client and their nicknames
clients = []
nicknames = []
#broadcast method to send message to all the clients connected to the server
def broadcast(message):
for client in clients:
client.send(message)
def handle (client):
while True:
try:
message = client.recv(1024)
broadcast(message)
except: #if the connection is lost, discard the client
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
broadcast(f'{nickname} already left the chat!'.encode('ascii'))
nicknames.remove(nickname)
break
#function to receive connection
def receive():
while True:
client, address = server.accept()
print(f"Conncected with {str(address)}")
client.send('NICKNAME'.encode('ascii'))
nickname = client.recv(1024).decode('ascii')
nicknames.append(nickname)
clients.append(client)
print(f'The nickname of the client is {nickname}')
broadcast(f'{nickname} joined the chat!'.encode('ascii'))
client.send('Connected to the server!'.encode('ascii'))
#making thread for every client
thread = threading.Thread(target = handle, args = (client,))
thread.start()
print("Server is waiting for client...")
receive() # runs the function that accepts for incoming connections
The client code should run the write() function on the main thread and not on another one, because it requires input from the stdin. You can change your code as follows in order to run the receiving routine on another thread and your "writing" function on the main one.
import socket
import threading
#nickname prompt
nickname = input("Input your nickname: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#binding the client to the port
client.connect(('127.0.0.1', 9879))
def receive():
while True:
try:
message = client.recv(1024).decode('ascii')
if message == 'NICKNAME':
client.send(nickname.encode('ascii'))
else:
print(message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{nickname}: {input("")}'
client.send(message.encode('ascii'))
#making the thread
receive_thread = threading.Thread(target = receive)
receive_thread.start()
# on the main thread
write()
The cause of the Connection refused error was due to the fact that the server code immediately exited since the receive function was never actually called.

Python connecting two clients to a server causes the first client to break

I'm trying to create a simple python chat interface however when two clients are connected to the server, the first clients console prints blank spaces as quick as possible and causes a max recursion depth error while the second client still works fine. The server code only sends data when its not blank so i'm not sure why it does this.
Server code:
import socket
from threading import Thread
from socketserver import ThreadingMixIn
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print("[+] New thread started for "+ip+": "+str(port))
def run(self):
while True:
data = conn.recv(1024).decode()
if not data: break
if data == "/exit":
print("Connection for "+ip+" closed.")
data = "Connection closed."
conn.send(data.encode())
break
else:
print("received data: ", data)
if data != " ":
conn.send(data.encode())
print("connection "+ip+" force closed.")
TCP_IP = socket.gethostname()
TCP_PORT = 994
BUFFER_SIZE = 1024
tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpsock.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpsock.listen(4)
(conn, (ip,port)) = tcpsock.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
Client code:
import socket
import threading
from threading import Thread
TCP_IP = socket.gethostname()
TCP_PORT = 994
BUFFER_SIZE = 1024
name = str(input("Input username: "))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
def recv():
while True:
data = s.recv(BUFFER_SIZE).decode()
if not data: break
print(data)
recv()
def send():
message = str(input())
if message != "/exit":
message = name + ": " + message
s.send(message.encode())
send()
if __name__ == "__main__":
Thread(target = recv).start()
Thread(target = send).start()
The error is at line 19 in the client code (where its receiving and printing any data sent by the server)
Any help would be greatly appreciated.
The most probable reason is the recursion in your send and receive routines, I changed them to be loops instead.
def recv():
while True:
data = s.recv(BUFFER_SIZE).decode()
if not data: break
print(data)
def send():
while True:
message = str(input())
if message != "/exit":
message = name + ": " + message
s.send(message.encode())
A solution to shutting down these threads is given here: Is there any way to kill a Thread in Python?
But it is not necessary to run send and receive in single threads in this scenario in the clients.
EDIT:
I read again carefully your code. In the client you start the send and receive method as threads. The send thread does not get any input for its message string in the thread and because you loop it, it sends empty messages to the server or (in my case) exits with an error.

using select() method for client/ server chat in Python

I am writing a client/ server program in Python where, once the client and server have successfully connected via a socket, they may exchange messages. Below is my server and client code. When compiled, the connection is established correctly and the messages are sent successfully, but one cannot send a second message until it has received a response from the other party.
For example:
Client sends: "Hello, server!"
Server sends: "I have received your message, client!"
Client sends: "great, here's another one"
Client sends: "and a second one!"
At this point, the server terminal window has received the message saying "great, here's another one", but must first reply to this message before receiving "and a second one!".
I think my issue is that I need to use the select() method, but do not understand how to do so. How can I fix this?
#The server code
HOST = ''
PORT = 9999
s = socket(AF_INET, SOCK_STREAM)
s.bind((HOST, PORT))
print("Now listening...")
s.listen(1) #only needs to receive one connection (the client)
conn, addr = s.accept() #accepts the connection
print("Connected by: ", addr) #prints the connection
i = True
while i is True:
data = conn.recv(1024) #receives data
print('Received:' , repr(data)) #prints the message from client
reply = raw_input() #server types a response
conn.sendall(reply) #server now sends response back to client
close()
below is the client code (client.py)
The client code
from socket import*
HOST = '192.168.41.1'
PORT = 9999
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT))
while True:
message = raw_input() #client's message to the server
s.send(message) #sends message to the server
print("Waiting for response...")
reply = s.recv(1024) #receives message from server
print("New message: " + repr(reply)) #prints the message received
close()
Look at the following examples:
http://code.activestate.com/recipes/531824-chat-server-client-using-selectselect/
and
http://www.binarytides.com/code-chat-application-server-client-sockets-python/
also some similar answer here:
Python client side in chat
What you are missing is select on client side where its select if to handle input from server or from command line.
So in that case, you don't have to wait for server response and can send 2 calls one after another from the client.
Freely adapting the answers above to what you wished to accomplish.
(I didn't test it - so make sure to check it)
from socket import*
import sys
import select
HOST = '192.168.41.1'
PORT = 9999
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST, PORT))
while True:
socket_list = [sys.stdin, s]
# Get the list sockets which are readable
read_sockets, write_sockets, error_sockets = select.select(
socket_list, [], [])
for sock in read_sockets:
#incoming message from remote server
if sock == s:
data = sock.recv(1024)
if not data:
print('\nDisconnected from server')
break
else:
#print data
sys.stdout.write(data)
# prints the message received
print("New message: " + repr(data))
prompt()
#user entered a message
else:
msg = sys.stdin.readline()
s.send(msg)
prompt()
s.close()
I would strongly suggest reading and familiarizing with this document and especially the non-blocking sockets part.
Your code now blocks when waiting for the data to arrive from the user. You want to instruct your program to wait for the data from the socket and at the same time allow user to type input.

Threading - How to recieve and reply at the same time using the socket module?

I am trying to make a simple LAN instant messager where many clients connect to the server and the server replies back and can see what the client is saying. I have tried but my lack of knowledge using the threading module has limited me. At the moment, however, the server only gets a message and has to reply to get the next one. I am trying to make it so the server can see all the messages it receives instantly and can reply whenever he need to. How?
Server Code:
from threading import *
import socket
s = socket.socket()
host = socket.gethostbyname(socket.gethostname())
port = 1337
s.bind((host, port))
s.listen(5)
def getMainThread():
for thread in enumerate(): # Imported from threading
if thread.name == 'MainThread':
return thread
if thread.name == 'Thread':
return thread
return None
class client(Thread):
def __init__(self, socket, address):
Thread.__init__(self)
self.socket = socket
self.address = address
self.start() # Initated the thread, this calls run()
def reply(self):
reply = getThread()
while reply and reply.isAlive():
sent = input("Enter Message: ")
self.socket.send(bytes(sent, 'UTF-8'))
def run(self):
main = getMainThread()
while main and main.isAlive():
message = self.socket.recv(8192).decode('utf-8')
self.socket.send(b"Got your message.. send another one!")
print('Someone:',message)
sent = input("Enter Message: ")
self.socket.send(bytes(sent, 'UTF-8'))
self.socket.close()
while True:
c, addr = s.accept()
client(c, addr)
Client Code:
import socket
host = socket.gethostbyname(socket.gethostname())
print("""
================================================================================
Welcome to Coder77's local internet message for avoiding surveillance by the NSA
================================================================================
The current soon to be encrypted server is {0}
""".format(host))
#host = input("Please select the IP you would like to communicate to: ")
print("Now connecting to {0}....".format(host))
sock = socket.socket()
try:
sock.connect((host, 1337))
while True:
message = input("Enter Message: ")
if message == 'quit':
break
sock.send(bytes(message, 'UTF-8'))
recieved = sock.recv(8192).decode('utf-8')
print('Server responded with:', recieved)
except socket.error:
print ("Host is unreachable")
sock.close()
Also, is it possible using Threading so that 2 while statements can run at the same time? If so, can someone give me an example?
Boosting this to try and get an answer. Anyone?

Categories

Resources