Python sockets not sending data immediately - python

I am making a game in python. It uses sockets. It is my first time using sockets.
Here is part of my code:
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# get local machine name
host = socket.gethostname()
port = 9999
# bind to the port
serversocket.bind((host, port))
# queue up to 5 requests
serversocket.listen(5)
player = 1
keys = []
playerSockets = []
print "Waiting for players..."
while True:
# establish a connection
clientsocket, addr = serversocket.accept()
key = id_generator()
keys.append(key)
playerSockets.append(clientsocket)
clientsocket.send(str(player)+"\r\n")
clientsocket.send(str(key)+"\r\n")
print "Player " + str(player) + " connected."
player = player + 1
if player > 3 or currentEpochtime() > endConn:
break
print str(player-1) + " active players.\n"
if(player < 3):
print "Not enough Players. Closing..."
serversocket.close()
quit()
#Other Stuff Continues
Now, it only sends the above data (player and key) only after the next send statement comes in my code. But then, that next send statement never sends because it is waiting for a reply from the client. But the client is not sending anything as it still hasn't received the data from the previous send statement in the server.
I have been trying to find a solution for a very long time, but cannot do so.
Please help!

Not quite sure about your question, do you mean client couldn't receive info from server?
I try with the following client code:
import socket
s = socket.socket()
host = socket.gethostname()
port = 9999
s.connect((host, port))
print s.recv(1024)
input = raw_input('type anything and click enter... ')
s.send(input)
print "the message has been sent"
It seems to receive data sent by server and be able to send data back to server.
Does this help?

Related

Rock-paper-scissors game using sockets in Python

I would like to write a very simple rock-paper-scissors game in Python. I would like to have 1 server and 2 clients. After connecting to the server, the server should send a message to each client to choose (r/p/s). After this, each client should send back their choice and the server then decides about the winner, and then it informs the clients about the winner.
This is what I have so far:
This is the server.py
import socket
from threading import Thread
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(1024).decode()
print("Server received data:", data)
MESSAGE = input("Server response: ")
if MESSAGE == 'exit':
break
conn.send(MESSAGE.encode())
TCP_IP = '0.0.0.0'
TCP_PORT = 2004
BUFFER_SIZE = 1024
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpServer.listen(4)
print("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip, port)) = tcpServer.accept()
newthread = ClientThread(ip, port)
newthread.start()
threads.append(newthread)
for t in threads:
t.join()
This is clientA.py:
import socket
host = socket.gethostname()
port = 2004
BUFFER_SIZE = 1024
MESSAGE = input("tcpClientA:")
tcpClientA = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientA.connect((host, port))
while MESSAGE != 'exit':
tcpClientA.send(MESSAGE.encode())
data = tcpClientA.recv(BUFFER_SIZE).decode()
print(" ClientA received data:", data)
MESSAGE = input("tcpClientA:")
tcpClientA.close()
This is clientB.py:
import socket
host = socket.gethostname()
port = 2004
BUFFER_SIZE = 1024
MESSAGE = input("tcpClientB:")
tcpClientB = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpClientB.connect((host, port))
while MESSAGE != 'exit':
tcpClientB.send(MESSAGE.encode())
data = tcpClientB.recv(BUFFER_SIZE).decode()
print(" ClientB received data:", data)
MESSAGE = input("tcpClientB:")
tcpClientB.close()
In this code, however, I can only send messages to the server and it can respond. Unfortunately, I don't know, how I can send messages to a specific client in this case. (I need to send different messages to the winner and to the loser).
First, this is not a trivial exercise and it will require a decent understanding of how threads work and how to work with them in Python in particular. What you seem to be missing at the moment is a way of orchestrating the communication from the 2 clients and of keeping track of what each client played so you can decide which client wins.
What currently happens is that when tcpClientA.connect((host, port)) runs on client A, (conn, (ip, port)) = tcpServer.accept() gets unblocked in the server. This creates a new instance of your ClientThread class and the new thread starts listening for data to be sent by client A on the connection. When client B runs, the same happens and you now have 2 threads running and listening for data but no way of knowing which plays what.
What I would suggest is to introduce a new class that will represent the game itself. That class will get the messages from both client and respond to each accordingly. What you will also need is a way of waiting for both clients to have played their turn before being able to decide who wins and what to send to each.
One way to do it would be with Barrier objects.

Send messages received by server to multiple clients in python 2.7 with socket programming

So I have created a socket program for both client and server as a basic chat. I made it so the server accepts multiple clients with threading, so that is not the problem. I am having trouble sending messages to each client that is connected to the server. I am not trying to have the server send a message it created but rather have client1 sending a message to client2 by going through the server. For some reason it will only send it back to client1.
For example, client1 will say hello and the server will send the same message back to client1 but nothing to client2. I fixed this slightly by making sure the client doesn't receive its own message but client2 is still not receiving the message from the client1.
Any help will be appreciated.
I have tried multiple changes and nothing seems to work. You can look at my code for specifics on how I did things but ask if there are any questions.
Also, there is a question where someone has asked that is similar and I thought it would give me an answer but the responses stopped going through and a solution was never fully given, so please don't just refer me to that question. that is located here: Python 3: Socket server send to multiple clients with sendto() function.
Here's the code:
CLIENT:
import socket
import sys
import thread
#Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#Enter username to identify self to others
name = raw_input("Enter username: ") + ": "
#Connect socket to ip and port
host = socket.gethostname()
#host = '192.168.1.10'
server_address = (host, 4441)
sock.connect(server_address)
#function waiting to receive and print a message
def receive(nothing):
while True:
data = sock.recv(1024)
if message != data:
print data
# Send messages
while True:
#arbitrary variable allowing us to have a thread
nothing = (0, 1)
message = name + raw_input("> ")
sock.sendall(message)
#thread to receive a message
thread.start_new_thread(receive, (nothing,))
SERVER:
import socket
import sys
import thread
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
host = socket.gethostname()
server_address = (host, 4441)
sock.bind(server_address)
#Listen for incoming connections
sock.listen(5)
print "Waiting for connection..."
#Variable for the number of connections
numbOfConn = 0
#Name of list used for connections
addressList = []
#Function that continuosly searches for connections
def clients(connection, addressList):
while True:
message = connection.recv(1024)
print message
#connection.sendall(message)
#for loop to send message to each
for i in range(0,numbOfConn - 1):
connection.sendto(message, addressList[i])
connection.close()
while True:
#accept a connection
connection, address = sock.accept()
print 'Got connection from', address
numbOfConn += 1
addressList.append((address))
#Thread that calls the function: clients and stores them in a tuple called connection
thread.start_new_thread(clients, (connection, addressList))
sock.close()
Please help me if you can!
EDIT:
I was able to fix it to a certain extent. It is still a little buggy but I am able to send messages back and forth now. I needed to specify the connection socket as well as the address. Here's the updated code:
SERVER
import socket
import sys
import thread
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
host = socket.gethostname()
server_address = (host, 4441)
sock.bind(server_address)
#Listen for incoming connections
sock.listen(5)
print "Waiting for connection..."
#Variable for the number of connections
numbOfConn = 0
#Name of list used for connections
addressList = []
connectionList = []
#Function that continuosly searches for connections
def clients(connectionList, addressList):
while True:
for j in range(0,numbOfConn):
message = connectionList[j].recv(1024)
print message
#for loop to send message to each
for i in range(0,numbOfConn):
connectionList[i].sendto(message, addressList[i])
connection.close()
while True:
#accept a connection
connection, address = sock.accept()
print 'Got connection from', address
numbOfConn += 1
addressList.append((address))
connectionList.append((connection))
#Thread that calls the function: clients and stores them in a tuple called connection
thread.start_new_thread(clients, (connectionList, addressList))
sock.close()

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.

Python Socket - Multiple Clients

First as a disclaimer: I'm not the greatest at Python(or programming in general).
Having said that, I am having issues with Python Sockets. I am trying to build a simple chat client/server program, however, I am unable to have the server send the corresponding message(s) received from one client's socket, to the rest of the connected clients.
Here is the server code:
#!/usr/bin/python
import socket
import fnmatch
import thread
serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
## Allow socket to be reused by application - doesn't force timeout.
serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
host = socket.gethostname()
port = 9000
serverSocket.bind((host,port))
connectedUsers = []
serverSocket.listen(5)
def threadedClient(clientStream):
while True:
clientMessage = clientStream.recv(1024).decode()
print clientMessage
if "Username:" in clientMessage:
username = clientMessage.replace("Username:","")
print str(username) + " has connected!"
connectedUsers.append(clientAddress)
print str(username) + "" + str(clientAddress) + " has connected to server"
for users in connectedUsers:
clientStream.sendto(str(username) + " has connected!", users)
if "Text:" in clientMessage:
receievedText = clientMessage.replace("Text:","")
for users in connectedUsers:
clientStream.sendto(receievedText.encode(), users)
print "Sending message " + str(receievedText) +" to:" + str(users)
if not clientMessage:
break
while True:
clientStream, clientAddress = serverSocket.accept()
thread.start_new_thread(threadedClient,(clientStream,))
Here is the client code:
#!/usr/bin/python
import socket
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 9000
username = raw_input("Please enter username: ")
clientSocket.connect((host, port))
clientSocket.send("Username:" + username)
def receiveServerMessage():
serverMessage = clientSocket.recv(1024).decode()
print serverMessage + '\n'
while True:
receiveServerMessage()
command = raw_input(username + " > ")
if command != None:
clientSocket.send("Text:" + str.encode(command))
if command == str("q"):
exit()
clientSocket.close()
The iteration seems to be awry when attempting to send the message to the other connected clients. I'm not sure if "sendto" is the proper way of handling this situation...especially since I believe it is UDP based. Any suggestions on how to handle socket stream correctly?
the problem is that the client is listening to the keyboard input before listening to the server socket , the best way to solve this is by using select() which similar to select() in c
here is a good example https://pymotw.com/2/select/

socket.send working only once in python code for an echo client

I have the following code for an echo client that sends data to an echo server using socket connection:
echo_client.py
import socket
host = '192.168.2.2'
port = 50000
size = 1024
def get_command():
#..Code for this here
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
while 1:
msg = get_command()
if msg == 'turn on':
s.send('Y')
elif msg == 'turn off':
s.send('N')
elif msg == 'bye bye':
break
else:
s.send('X')
data = s.recv(size)
print 'Received: ',data
s.close()
echo_server.py
import socket
host = ''
port = 50000
backlog = 5
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(backlog)
while 1:
client, address = s.accept()
data = client.recv(size)
if data:
client.send(data)
client.close()
The problem im facing is that in the client s.send works only the first time even though its in an infinite loop. The client crashes with connection timed out, some time after the first send/receive has completed.
Why is s.send working only once ?. How can i fix this in my code ?
Please Help
Thank You
Your server code only calls recv once. You should call accept once if you only want to receive one connection, but then you need to loop calling recv and send.
Your problem is that you are blocking on the accept inside the server's loop.
This is expecting the server to accept connections from more than one client. If you want that, and for each client to send multiple commands, you would need to spawn a new thread (or process) after the accept, with a new while loop (for client communication) in that thread/process.
To fix your example to work with just one client, you need to move the accept outside the loop, like so:
client, address = s.accept()
while 1:
data = client.recv(size)
if data:
client.send(data)

Categories

Resources