I'm working on a very simple python socket server. I use non-blocking sockets. The server and client are running on windows 7 x64 with python 2.7.3. Here is the code where I receive data from the client :
def listenToSockets(self):
while True:
changed_sockets = self.currentSockets
ready_to_read, ready_to_write, in_error = select.select(changed_sockets,[],[])
for s in ready_to_read:
# if its the server master socket someone is connecting
if s == self.socket:
(client_socket, address) = s.accept()
print "putting " + address[0] + " onto connections\n";
client_socket.setblocking(0)
self.currentSockets.append(client_socket)
print "current client count : " + str(len(self.currentSockets) - 1)
else:
data = ''
try:
while True:
part = s.recv(4096)
if part != '':
data = data + part
elif part == '':
break
except socket.error, (value,message):
print 'socket.error - ' + message
if data != '':
print "server received "+data
else:
print "Disconnected "+str(s.getsockname())
self.currentSockets.remove(s)
s.close()
And here is the client sending some data over and over again :
#client example
import socket
import time
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(('192.168.0.41', 9999))
while 1:
client_socket.send("test")
time.sleep(2)
I see the server receiving the message "test" over and over again. But before it prints out what it received I get the following error message.
socket.error - A non-blocking socket operation could not be completed immediately.
Obviously an exception is thrown at part = s.recv(4096) but why?
That's precisely what a nonblocking socket is supposed to do.
Read the available data, if any
If nothing is available, raise an error rather than blocking
So you're getting an exception every time you try to receive and there's no data available.
Related
I amusing a client to send a message to a python server.
client side: client.send("1")
Server side:
d=clientsocket.recv(1024)
if (d=="1"):
print(" Correct value")
It won't print correct value. I know the error at recv as I don't know how it works. Could anyone please help me to solve this matter.
You just need simple modification to work it correctly:-
in client correct like below:-
client.send("1".encode())
in server correct like below:-
d=clientsocket.recv(1024).decode()
if (d=="1"):
print(" Correct value")
I have created one client and server for you which is working fine in Python 3.4. Please try and check:
Here is your server
import socket
import sys
HOST = "localhost"
PORT = 8000
print("Creating socket...")
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Binding socket...")
try:
sc.bind((HOST, PORT))
except socket.error as err:
print("Error binding socket, {}, {}".format(err[0], err[1]))
print("bound Successful")
# Configure below how many client you want that server can listen to simultaneously
sc.listen(2)
print("Server is listening on {}:{}".format(HOST, PORT))
while True:
conn, addr = sc.accept()
print("Connection from: " + str(addr))
print("Receiving data from client\n")
data = conn.recv(1024).decode()
print("Client says :" + data)
if(data == "2"):
print(" Ooh you are killing me with value :" + data)
conn.sendall(str.encode("\n I am server and you killed me with :" + data))
break;
elif(data == "1"):
print(" Correct value :" + data)
conn.sendall(str.encode("\n I am server and you hit me with correct value:" + data))
else:
print(" You are sending a wrong value :" + data)
conn.sendall(str.encode("\n I am server and you hit me with wrong value :" + data))
sc.close()
and now your client is here:-
import socket
import sys
HOST = "localhost"
PORT = 8000
print("creating socket")
sc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Connecting to host")
try:
sc.connect((HOST, PORT))
except socket.error as err:
print("Error: could not connect to host, {}, {}".format(err[0], err[1]))
sys.exit()
print("Connection established to host")
message = "1" # Run client 3 times with value message = '1' and '5' and '2'
sc.send(message.encode())
data = sc.recv(1024).decode()
print("Server response is : " + data)
sc.close()
I'm stuck on this socket communication, I've looked everywhere but I haven't found an answer yet.
THE PROBLEM: I can only send 1 message from the client before it either gives me an error or ends the script.
I need to be able to send multiple messages to the server.
The server side (shown below) should be fine:
# Echo server program
import socket
import time
import os
#-----------------------------------------------------------------------------------------------------------------------
today = time.strftime('%Y.%m.%d')
logFileName = "log - " + today + ".txt"
HOST = '10.0.0.16'
PORT = 8080 # Reserve a port for your service
BUFFER_SIZE = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Create a socket object
s.bind((HOST, PORT)) # Bind to the port
def print_write(text):
log.write(time.strftime("%H:%M:%S") + " | " + text)
log.write("\n")
print text
#-----------------------------------------------------------------------------------------------------------------------
if os.path.isfile(logFileName) is True:
log = open(logFileName, 'a+')
print_write("[SERVER] Log for " + today + " already exists.")
print_write("[SERVER] Starting comms")
else:
print "[SERVER] Log doesn't exist"
log = open(logFileName, 'a+') # Create file -> log - %date%.txt
print_write("[SERVER] Log created")
while True:
s.listen(1)
conn, addr = s.accept()
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
log.close()
Sorry if it's very messy and confusing but i don't have much time to finish this project, if you have any question just ask.
For the client side I don't have much but here, I'll give you this:
import socket
HOST = '10.0.0.16' # The remote host
PORT = 8080 # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
msg = raw_input()
s.sendall(msg)
print msg
I know it doesn't work, it's just to give you an idea of what I need.
Thank you in advance.
The problem is, that you only read the first message from each open connection before moving on to the next. The accept() methods waits for a new connection and gives you the information needed when a new one comes in. the recv() method on the other hand, receives data from a existing connection and waits if there is none. If you want to receive multiple messages from a single client, you can just wait for the first connection and then wait for data with recv(). This could look like this:
s.listen(1)
conn, addr = s.accept()
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
If you want to be able to also manage multiple clients, you will have to create a thread for each one from a while loop waiting for new connections. This is a bit more complicated:
def client_handler(conn):
while True:
data = conn.recv(BUFFER_SIZE)
if data == "Comms Shutdown":
print_write("------ REMOTE SHUTDOWN ------")
conn.close()
raise SystemExit
# this will kill the server (remove the line above if you don't want that)
else:
print_write("[COMMS] " + str(addr) + " says: " + data)
while True:
s.listen(1)
conn, addr = s.accept()
recv_thread = threading.Thread(target=client_handler, args=(conn, ))
recv_thread.start()
All this code is untested. Be aware, that I omitted the logging part and the socket creation part as well as all imports.
I am creating a simple chat in python 3 using socket
here are the code
CLIENT
#!/bin/python
import socket
import threading
import time
tLock = threading.Lock()
poweroff = False
def receving(name, sock):
while not poweroff:
try:
tLock.acquire()
while True:
data, addr = sock.recvfrom(1024)
print (str(data))
except:
pass
finally:
tLock.release()
host = '127.0.0.1'
port = 0
server = ('127.0.0.1', 5000)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
s.setblocking(0)
rT = threading.Thread(target=receving, args=("RecvThread", s))
rT.start()
alias = input("Username: ")
time.sleep(0.2)
message = input(alias + ">>> ")
while message != 'q':
if message != "":
s.sendto(str(alias + ": " + message).encode('utf-8'), server)
tLock.acquire()
message = input(alias + ">>> ")
tLock.release()
time.sleep(0.2)
poweroff = True
rT.join()
s.close()
SERVER
#!/bin/python
import socket
import time
hostname = '127.0.0.1'
port = 5000
clients = []
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((hostname, port))
s.setblocking(0)
iQuit = False
print ("Server Started.")
while not iQuit:
try:
data, addr = s.recvfrom(1024)
if addr not in clients:
clients.append(addr)
print (time.ctime(time.time()) + str(addr) + ": :" + str(data))
for client in clients:
s.sendto(data, client)
except:
pass
s.close()
How do i print a string to the server when a user connect?
I have tried to add this string after you have insert the name
s.sendto(str(alias + " Connected").encode('utf-8'), server)
but the output is orrible for me
Another Question:
Why i get something like this when seding a message?
Username: User_A
User_A>>> Hello
User_A>>> How Are you?
b'User:A: Hello'
User_A>>>
b'User_A: How Are you?'
b'User_B: Hi'
Concerning your second question: You are printing binary strings, see here for more information.
Use str(data.decode('utf-8')) instead of str(data) when printing the message on the server or the client.
Concerning the first question: This should work if you send the "Connected" string just after asking for the user name.
The string is decoded the same way as a common message if you include the decode('utf-8') and looks normal to me.
i have to press enter to see if user_B send something to me.
You enforced this behavior by locking out the receiving thread during the input of a message. You have to make up your mind whether you want this or want incoming data to be printed while typing.
You might want to cf. Simultaneous input and output for network based messaging program.
I am trying to establish a connection to a server, and send some data to it..
The problem is that, if i try to debug the connection using this MICHAEL SIEGENTHALER | TCP/UDP Debugging Tools
which clearly shows that there is no issue with the communication, and even some form of random input will result in a data coming out.
but when i try to code it in python, using the same settings, are no response received.. It stalls after it has sent the message, i am not sure whether whether it has send the message, or skipped it?
It seems like my server aren't receiving the message i sent to it, and therefore don't reply.. but what is different?
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ('Failed to create socket')
sys.exit()
host = 'localhost';
port = 5634;
while(1) :
try :
#Set the whole string
s.sendto(("-1-117230").encode('utf-8'),('10.2.140.183', 9008))
print("sent")
# receive data from client (data, addr)
d = s.recvfrom(1024)
reply = d[0]
addr = d[1]
print ('Server reply : ' + reply)
except socket.error as msg:
print ('Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
what is different from the code, and the way the debugging tool test it?
I tried to code it in c++ using boost, but as i had the same issue, i went on to trying in python to see whether that would make a bit more sense.
---Updated --
import socket #for sockets
import sys #for exit
# create dgram udp socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_adress = ('10.2.140.183',5634)
s.bind(server_adress)
except socket.error:
print ('Failed to create socket')
sys.exit()
while(1) :
try :
#Set the whole string
s.sendto(("-1-117230").encode('utf-8'),('10.2.140.183', 9008))
print("sent")
# receive data from client (data, addr)
d = s.recvfrom(1024)
reply = d[0]
addr = d[1]
print ('Server reply : ' + reply)
except socket.error as msg:
print ('Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
You are missing the binding method.
This is kind of an echo server:
import socket
import sys
host = ''
port = 8888
buffersize = 1
server_address = (host, port)
socket_UDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
socket_UDP.bind(server_address)
while True:
data, from_address = socket_UDP.recvfrom(buffersize)
if data:
socket_UDP.sendto(bytes("b"*buffersize, "utf-8"), from_address)
socket_UDP.close()
I have a twisted server script listening on a unix socket and it receives the data when the client is in twisted but it doesn't work if i send it via a vanilla python socket code.
class SendProtocol(LineReceiver):
"""
This works
"""
def connectionMade(self):
print 'sending log'
self.sendLine(self.factory.logMessage)
if __name__ == '__main__':
address = FilePath('/tmp/test.sock')
startLogging(sys.stdout)
clientFactory = ClientFactory()
clientFactory.logMessage = 'Dfgas35||This is a message from server'
clientFactory.protocol = SendProtocol
port = reactor.connectUNIX(address.path, clientFactory)
reactor.run()
But this doesn't (server doesn't get any data)
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock_addr = '/tmp/test.sock'
try:
sock.connect(sock_addr)
except socket.error, msg:
print >> sys.stderr, msg
sys.exit(1)
sock.setblocking(0) # not needed though tried both ways
print 'connected %s' % sock.getpeername()
print 'End END to abort'
while True:
try:
line = raw_input('Enter mesg: ')
if line.strip() == 'END':
break
line += '\n'
print 'sending'
sock.sendall(line)
finally:
sock.close()
Your two client programs send different data. One sends \r\n-terminated lines. The other sends \n-terminated lines. Perhaps your server is expecting \r\n-terminated lines and this is why the latter example doesn't appear to work. Your non-Twisted example also closes the socket after the first line it sends but continues with its read-send loop.