I am making a chat interface, and currently, the server has to send a message first in order for the chatting to work.
If the client sends a message first, then the server cannot see the message until the server sends a message to the client.
My question:
How can I check if the client has sent anything to me? Then I can simply print it out.
Here is the server code:
serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serv.bind(("", 8080))
serv.listen(5)
while True:
c, addr = serv.accept()
print("Connection recieved from", addr)
while True:
strig = str(input("Enter your message to the client: "))
c.send(strig.encode())
thing = c.recv(1024)
message = list(str(thing))
message.remove("b")
printable = ""
for item in message:
printable += item
print(printable)
strig = str(input("Enter your message to the client: "))
c.send(strig.encode())
thing = c.recv(1024)
message = list(str(thing))
message.remove("b")
printable = ""
for item in message:
printable += item
print(printable)
And here is the client code:
from time import sleep
s = socket.socket()
port = 8080
s.connect(("10.0.0.92", port))
while True:
thing = str(s.recv(1024))
message = list(thing)
message.remove("b")
#message.remove("/")
printable = ""
for item in message:
printable += item
print(printable)
your = str(input("Enter your message to the server: "))
s.send(your.encode())
thing = str(s.recv(1024))
message = list(thing)
message.remove("b")
#message.remove("/")
printable = ""
for item in message:
printable += item
print(printable)
your = str(input("Enter your message to the server: "))
s.send(your.encode())
Thanks in advance!!
p.s. I want one person to be the server, and one person to be the client. Please don't tell me to make both people clients.
Your server is single-threaded. input waits for input so will never get to recv without user input. Create a thread to read client input and a thread to ask for and send messages. You'll need something similar on the client side.
Related
when I send message from client 1 , the message does not appear immediately in client 2 ,Although it appears immediately on the server, on client 2 i should double press "enter" to show other messages.
when I send message from client 1 , the message does not appear immediately in client 2 ,Although it appears immediately on the server, on client 2 i should double press "enter" to show other messages.
the server code :
import socket
import select
import sys
from _thread import *
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
if len(sys.argv) != 3:
print ("Correct usage: script, IP address, port number")
exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.bind((IP_address, Port))
server.listen(5)
list_of_clients = []
def broadcast(message, connection):
for clients in list_of_clients:
if clients!=connection:
try:
clients.send(message.encode())
except:
clients.close()
remove(clients)
def remove(connection):
if connection in list_of_clients:
list_of_clients.remove(connection)
def clientthread(conn, addr):
# sends a message to the client whose user object is conn
conn.send(b'chat made by galal')
while True:
try:
message = conn.recv(2048).decode()
if message:
print ("<" + addr[0] + "> " + message)
message_to_send = "<" + addr[0] + "> " + message
broadcast(message_to_send, conn)
else:
remove(conn)
except:
continue
while True:
conn, addr = server.accept()
list_of_clients.append(conn)
print (addr[0] + " connected")
start_new_thread(clientthread,(conn,addr))
conn.close()
server.close()
the client code :
import socket
import select
import sys
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
print ("Correct usage: script, IP address, port number")
exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))
while True:
# maintains a list of possible input streams
sockets_list = [socket.socket(), server]
read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
for socks in read_sockets:
if socks != server:
message = sys.stdin.readline()
server.send(message.encode())
sys.stdout.write("<You>")
sys.stdout.write(message)
sys.stdout.flush()
else:
message = socks.recv(2048).decode()
print (message)
server.close()
Your client code waits until pressed enter since there is a
sys.stdin.readline() in your client code (Line 17).
sys.stdin.readline() waits for the press of your enter key, since it tries to read a newline from your stdin (Your input), therefore blocking the whole execution of your client application.
What you have to do is using separate threads for:
Recieving messages + print them
Read from stdin (e.g. through sys.stdin.readline() or input()) and send that message to the server like you're already doing
I think the issue is the client's for loop.
sys.stdin.readline() stops the flow until Enter is pressed, so when you send a message from client1, client2 is still waiting for the user to write its own message. Basically since the first item in read_sockets is always socket.socket() every client's first action will be to wait for user input to send a message. The server on the other hand is always listening and never waits, so it receives it immediately.
To solve this you can either have an async connection, meaning you send 1 message then wait to receive 1 message and so on, or use multithreading and dedicate a thread to receiving and one to sending.
I asked a question about my server to client code because I had many problems with and someone told me that the solution to the problems I had was to make a peer to peer chat which I have now done.
Server.py
import socket, threading
host = "127.0.0.1"
port = 4000
s = socket.socket()
s.bind((host,port))
s.listen(5)
client_sockets = []
users = []
print("Listening")
def handle_client(conn):
while True:
try:
data = conn.recv(512)
for x in client_sockets:
try:
x.send(data)
except Exception as e:
print(e)
except:
pass
while True:
conn,addr = s.accept()
client_sockets.append(conn)
print("Connections from", addr[0], "on port",addr[1])
threading.Thread(target = handle_client,args = (conn,)).start()
Client.py
import socket,threading
host = "127.0.0.1"
port = 4000
s = socket.socket()
s.connect((host,port))
def echo_data(sock):
while True:
try:
data = sock.recv(512)
print(data)
except:
pass
while True:
threading.Thread(target=echo_data,args=(s,)).start()
msg = input("Enter your message : ")
s.send(msg.encode())
The problems is that when I run the client and try talking to another client the message doesn't get sent unless the other client hits enter and also that brings me to my second problem, when the clients send messages to each other they get received in this format:
b'hi'Enter your message :
This is the link to my previous question
I will start with general problems not directly related to the question:
except: pass is generally a bad idea, specially when things go wrong because it will hide potentially useful messages. It is allowed by the language but should never exist in real code
in client.py you start a receiving thread per message, while you only need one for the whole client. You should start the thread outside the loop:
threading.Thread(target=echo_data,args=(s,)).start()
while True:
msg = input("Enter your message : ")
s.send(msg.encode())
Now for the questions:
the message doesn't get sent unless the other client hits enter
It can be caused by an IDE. Specifically, IDLE is known to behave poorly with multi-threaded scripts. If you correctly use one single receiving thread and starts the script from the command line (python client.py) it should work correctly
the messages get recived in this format: b'hi'Enter your message
sock.recv(sz) returns a byte string. You need to decode it to convert it to a Python 3 unicode string:
data = sock.recv(512)
print(data.decode())
But that is not all. It is fine for tests, but you should at least allow clients to disconnect from the server and when they do, remove them from client_sockets. And it is common not to send back a message to the sender. So you could improve the server.py loop:
while True:
try:
data = conn.recv(512)
for x in client_sockets:
if x != conn: # do not echo to sender
x.send(data)
except Exception as e: # problem in connection: exit the loop
print(e)
break
# clear the connection
conn.close()
client_sockets.remove(conn)
I have followed a tutorial from a YouTuber under the name of DrapsTV. This tutorial was made in Python 2.7 and makes a networked chat using UDP. I converted this to Python 3 and got everything to work. However, the way the threading is setup is that I have to send a message(or press enter, which is a blank message) to refresh and receive any messages from other clients. Here is the video incase you may need it: https://www.youtube.com/watch?v=PkfwX6RjRaI
And here is my server code:
from socket import *
import time
address = input("IP Address: ")
port = input("Port: ")
clients = []
serversock = socket(AF_INET, SOCK_DGRAM)
serversock.bind((address, int(port)))
serversock.setblocking(0)
quitting = False
print("Server is up and running so far.")
while not quitting:
try:
data, addr = serversock.recvfrom(1024)
if "Quit" in str(data):
quitting = True
if addr not in clients:
clients.append(addr)
print(time.ctime(time.time()) + str(addr) + ": :" + str(data.decode()))
for client in clients:
serversock.sendto(data, client)
except:
pass
serversock.close()
Here is my client code:
from socket import *
import threading
import time
tLock = threading.Lock()
shutdown = False
def receiving(name, sock):
while not shutdown:
try:
tLock.acquire()
while True:
data, addr = sock.recvfrom(1024)
print(str(data.decode()))
except:
pass
finally:
tLock.release()
address = input("IP Address: ")
port = 0
server = address, 6090
clientsock = socket(AF_INET, SOCK_DGRAM)
clientsock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
clientsock.bind((address, int(port)))
clientsock.setblocking(0)
rT = threading.Thread(target=receiving, args=("RecvThread", clientsock))
rT.start()
nick = input("How about we get you a nickname: ")
message = input(nick + "> ").encode()
while message != "q":
if message != "":
clientsock.sendto(nick.encode() + "> ".encode() + message, server)
tLock.acquire()
message = input(nick + "> ").encode()
tLock.release()
time.sleep(0.2)
shutdown = True
rT.join()
clientsock.close()
#furas has kindly explained my issue for me: it is not my receiving methods that are flawed(such as my threading or functions), it is the input call that is preventing the client from not receiving anything. So, in order to fix this, I or anyone else having this issue needs to find a way to call for input when a certain button is pressed so that unless your typing, you can receive messages or data.
Thank you #furas! https://stackoverflow.com/users/1832058/furas
This is probably very simple, but I am having trouble with it.
This is code I am using for the server.
I've searched for this but I only found different kinds of sockets to the one I am using.
server = socket.socket()
server.bind(("localhost", 6969))
server.listen(1)
socket_client, datos_client = server.accept()
print ("Wainting message...")
data = socket_client.recv(1000)
print ("Message:", data)
send1 = bytes("Bye","utf-8")
socket_client.send(send1)
print ("Closing..." )
socket_client.close()
server.close()
And this is the code for the client:
import socket
def main():
my_socket_client = socket.socket()
my_socket_client.connect(("localhost", 6969))
bufsize = 1000
print("Send message")
message=input()
data2 = bytes(mensaje,"utf-8")
#enviar los datos
my_socket_client.send(data2)
data_received= my_socket_client.recv(bufsize)
print (data_received)
I am not sure what your problem is since you didn't ask a question so i will just show you a client + basic command server that i have built in the same way you built yours you said "I only found different kinds of sockets to the one I am using." so i hope this is what you are looking for
Here is an example of a simple command server:
if you run the server code and then run the client you will be able to type in the client and send to the server. if you type TIME you will get from the server a respons which contains a string that has the date of today and the other commands work in the same way. if you type EXIT it will close the connection and will send from the server the string closing to the client
server:
import socket
import random
from datetime import date
server_socket = socket.socket() # new socket object
server_socket.bind(('0.0.0.0', 8820)) # empty bind (will connect to a real ip later)
server_socket.listen(1) # see if any client is trying to connect
(client_socket, client_address) = server_socket.accept() # accept the connection
while True: # main server loop
client_cmd = client_socket.recv(1024) # recive user input from client
# check waht command was entered
if client_cmd == "TIME":
client_socket.send(str(date.today())) # send the date
elif client_cmd == "NAME":
client_socket.send("best server ever") # send this text
elif client_cmd == "RAND":
client_socket.send(str(random.randrange(1,11,1))) # send this randomly generated number
elif client_cmd == "EXIT":
client_socket.send("closing")
client_socket.close() # close the connection with the client
server_socket.close() # close the server
break
else :
client_socket.send("there was an error in the commend sent")
client_socket.close() # just in case try to close again
server_socket.close() # just in case try to close again
client:
import socket
client_socket = socket.socket() # new socket object
client_socket.connect(('127.0.0.1', 8820)) # connect to the server on port 8820, the ip '127.0.0.1' is special because it will always refer to your own computer
while True:
try:
print "please enter a commend"
print "TIME - request the current time"
print "NAME - request the name of the server"
print "RAND - request a random number"
print "EXIT - request to disconnect the sockets"
cmd = raw_input("please enter your name") # user input
client_socket.send(cmd) # send the string to the server
data = client_socket.recv(1024) # recive server output
print "the server sent: " + data # print that data from the server
print
if data == "closing":
break
except:
print "closing server"
break
client_socket.close() # close the connection with the server
you have a typo .
edit this line in client from
data2 = bytes(mensaje,"utf-8")
to
data2 = bytes(message,"utf-8")
I tried your code, and made a couple of changes:
Server side:
import socket
server = socket.socket()
server.bind(("localhost", 6969))
server.listen(1)
socket_client, datos_client = server.accept()
print ("Waiting message...")
data = socket_client.recv(1000)
print ("Message:", data )
# Same change made as with client side
send1 = bytes("Bye") #,"utf-8")
socket_client.send(send1)
print ("Closing..." )
socket_client.close()
server.close()
Client side:
import socket
my_socket_client = socket.socket()
my_socket_client.connect(("localhost", 6969))
bufsize = 1000
print("Send message")
# I changed it to raw_input(); input() does not for string input with python 2.7
message=raw_input()
# Are you trying to encode the message? To make it simple, skip it
data2 = bytes(message) # ,"utf-8")
#enviar los datos
my_socket_client.send(data2)
data_received= my_socket_client.recv(bufsize)
print (data_received)
Sample output from server side:
Waiting message...
('Message:', 'message from client')
Closing...
Sample output from client side:
Send message
message from client
Bye
I'm trying to develop a chat program in python. I want it to have multiple clients so I'm using threading to handle this. However when I try to send the message to all connected clients, the server only sends it to the client which sent the message. I'm not sure if I'm just missing something obvious but here is the code for the server:
import socket
from thread import *
host = '192.168.0.13'
port = 1024
users = int(input("enter number of users: "))
def clienthandler(conn):
while True:
data = conn.recv(1024)
if not data:
break
print data
conn.sendall(data)
conn.close()
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind((host, port))
serversock.listen(users)
for i in range(users):
conn, addr= serversock.accept()
print 'Connected by', addr
start_new_thread(clienthandler, (conn,))
And here is the code for the client:
import socket
host = '192.168.0.13'
port = 1024
usrname = raw_input("enter a username: ")
usrname = usrname + ": "
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsock.connect((host, port))
while True:
x = raw_input('You: ')
x = usrname + x
clientsock.sendall(x)
data = clientsock.recv(1024)
print data
The "all" in sendall means that it sends all of the data you asked it to send. It doesn't mean it sends it on more than one connection. Such an interface would be totally impractical. For example, what would happen if another thread was in the middle of sending something else on one of the connections? What would happen if one of the connections had a full queue?
sendall: Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. -- 17.2. socket
You can try by pulling up the list of users, and iterating through it, and doing an individual send of the same message, though, unless you are the administrator and want to broadcast a warning, this functionality would be pretty mundane.