I want a functionality to check if data is waiting in the socket to be read before reading it. Something like this would be helpful:
if (data available) then read data
else wait in blocking mode till data becomes available
How can I achieve this in Python
while 1:
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(4096)
if not data :
print '\nDisconnected from server'
sys.exit()
else :
#print data
sys.stdout.write(data)
#user entered a message
else :
msg = sys.stdin.readline()
s.send(msg)
Related
I am developing a python socket server. The client send each message to start with a STX (\x02) and end with ETX (\x03). My code can receive message successfully but I can't implement receiving full string using STX and ETX condition. Need help in resolving this issue. Below I have sharing my code for better understanding.
import socket
import time
# Start New RnD
# Global Veriable
enq = chr(5)
ack = chr(6)
stx = chr(2)
etx = chr(3)
# Connect to the server with `telnet $HOSTNAME 5000`.
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(False)
server.bind(('0.0.0.0', 5000))
server.listen(1)
connections = []
while True:
try:
connection, address = server.accept()
connection.setblocking(False)
connections.append(connection)
except BlockingIOError:
pass
# Incoming Data Processing
for connection in connections:
try:
full_message = ''
data = ""
while True:
try:
received = connection.recv(1)
if received == enq.encode('utf-8'):
print("Received <ENQ>, Sending <ACK>")
connection.sendall(ack.encode('utf-8'))
if not received:
raise RuntimeError("unexpected end-of-message", data)
data += received.decode('utf-8')
#print("Received: {!r}".format(data))
if "\x03" in received.decode("utf-8") :
break
except BlockingIOError:
pass
print("Full Received: {!r}".format(data))
print("Data Received, Sending <ACK>")
connection.sendall(ack.encode('utf-8'))
except BlockingIOError:
continue
this is my first entry #stackoverflow;-))
I need a Python3 TCP server, which sends all inputs of the clients to the other participants. The server works, but unfortunately the message is only returned to the sending client. As soon as the second client sends something, it gets all entries.The entries are therefore available in the output queue.
Why are the entries not recognized by select ()?
Thx for the support.
`
import select
import socket
import sys
import queue
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setblocking(0)
server_address = ('192.168.100.28', 8888)
print ("starting up on %s port %s" % server_address)
server.bind(server_address)
server.listen(5)
inputs = [ server ]
outputs = [ ]
message_queues = {}
while inputs:
print ("\nwaiting for the next event")
readable, writable, exceptional = select.select(inputs, outputs, inputs)
Handle inputs
for s in readable:
if s is server:
# A "readable" server socket is ready to accept a connection
connection, client_address = s.accept()
print ("new connection from", client_address)
connection.setblocking(0)
inputs.append(connection)
# Give the connection a queue for data we want to send
message_queues[connection] = queue.Queue()
else:
data = s.recv(1024)
if data:
# A readable client socket has data
print ('received "%s" from %s' % (data, s.getpeername()))
# Add output channel for response
#message_queues[s].put(data)
if s not in outputs:
outputs.append(s)
for aQueue in message_queues:
message_queues[aQueue].put(data)
# AQueue.send ("Test".encode())
else:
# Interpret empty result as closed connection
print ("closing", client_address, "after reading no data")
# Stop listening for input on the connection
if s in outputs:
outputs.remove(s)
inputs.remove(s)
s.close()
# Remove message queue
del message_queues[s]
Handle outputs
for s in writable:
try:
next_msg = message_queues[s].get_nowait()
except queue.Empty:
# No messages waiting so stop checking for writability.
print ("output queue for", s.getpeername(), "is empty")
outputs.remove(s)
else:
print ('sending "%s" to %s' % (next_msg, s.getpeername()))
s.send(next_msg)
Handle "exceptional conditions"
for s in exceptional:
print ("handling exceptional condition for", s.getpeername())
# Stop listening for input on the connection
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
# Remove message queue
del message_queues[s]
`
Your problem is that you only add a peer to the output list when you read something from it. You should instead do it when you write somthing to its message queue.
The receiving part should become:
...
data = s.recv(1024)
if data:
# A readable client socket has data
print ('received "%s" from %s' % (data, s.getpeername()))
# Add output channel for response
#message_queues[s].put(data)
# if s not in outputs:
# outputs.append(s)
for aQueue in message_queues:
message_queues[aQueue].put(data)
if aQueue not in outputs: # enqueue the msg
outputs.append(aQueue) # and ask select to warn when it can be sent
# AQueue.send ("Test".encode())
else:
...
According to your own requirements, you should only enqueue messages for other participants:
for aQueue in message_queues:
if aQueue != s: # only send to other participants
...
Finally, you often test existence of a socket in outputs. That let think that a set would be more appropriate than a list.
I have to write a code that allows non-blocking recv (along with non-blocking accept)
The following is what I got so far:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('', int(PortEntry_Page2_Text))
sock.bind(server_address)
sock.setblocking(0)
sock.settimeout(1)
sock.listen(1)
EnterToTerminal2("Listening to port "+str(PortEntry_Page2_Text)+"..")
EnterToTerminal2("Waiting for a connection. Press STOP to cancel.")
connected = 0
while (StopButtonStatePage2 == 0 and connected == 0):
try:
connection, client_address = sock.accept()
EnterToTerminal2("Connection from "+ str(client_address)+"..")
connected = 1
except Exception as inst:
template = "An exception of type {0} occured. Arguments:\n{1!r}"
message = template.format(type(inst).__name__,inst.args)
print message
finally:
if (connected == 0):
EnterToTerminal2("No client connected..")
StopButtonStatePage2 = GetStopButtonStatePage2()
###########################################
StopButtonStatePage2 = 0
sock.setblocking(0) ##?
print "xx0 "+str(connected)+" "+str(StopButtonStatePage2)
while (connected == 1 and StopButtonStatePage2 == 0):
a = select.select([sock], [], [], 1) # steelkiwi.com/blog/working-tcp-sockets
if a[0]:##?
data = sock.recv(64) # or connection.recv ??
EnterToTerminal2("Data recv: "+str(data))
StopButtonStatePage2 = GetStopButtonStatePage2()
Until sock.recv part, it works as expected. Now, the problem is that with the select approach, it does not enter the a[0] condition at all, even though I send stuff from client. Basically what I'm trying to achieve is to make recv part non-blocking/or with timeout so that I can stop its operation with a button, whenever I want.
Any help is appreaciated. Thanks in advance.
I found the following code on another post that works pretty good:
UDP_IP = ''
UDP_PORT = 5008
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', UDP_PORT))
while 1:
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(4096)
if not data :
print '\nDisconnected from server'
sys.exit()
else :
#print data
sys.stdout.write(data)
#user entered a message
else :
msg = sys.stdin.readline()
s.send(msg)
The problem I've got is with the for loop since it only runs through it when there is data received. I would really like it to use a while loop and have it occasionally check on if data has been received but I can't figure out how to do this.
Use the timeout parameter in the select statement. If no data is available (indicated by empty lists), you can do whatever other processing is needed in the body of the while loop.
I'm making a UDP program that connects multiple clients/neighbors. There is no server everyone is using the same program. I'm trying to test it with localhost so consider all IPs and ports of neighbors work as intended. Using 127.0.0.1 as IP on all and connecting to different ports.
So my question is why do I receive the startup data that I send before the while loop but I cannot send any? Seems that I am doing something wrong with sys.stdin.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((HOST, PORT))
going = True
input = [s]
while going:
i,o,e = select.select(input,[],[],)
try :
for x in i:
if x == sys.stdin:
data = sys.stdin.read()
for i in neighbors:
addr = (i[1][0], int(i[1][1]))
s.sendto(data, addr)
else:
msg, addr = s.recvfrom(100)
print msg
except socket.error, msg:
print 'Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
s.close()
input is always [s], so i is always going to be [s], so x == sys.stdin is never going to be True (because x is always s), so only the else clause will ever execute.
Maybe you meant input = [s, sys.stdin]?