How to Wait Until I Receive Data Using a Python Socket

How to wait for any socket to have data?

You can use select.select for your problem:

sockets = [sock1, sock2, sock3]
while sockets:
rlist, _, _ = select.select(sockets, [], [])
for sock in rlist:
do_stuff(sock)
sockets.remove(sock)

How to use a socket without waiting in python

You can use sockets in non-blocking mode:

import pygame as pg
import socket

pg.init()

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(("localhost", 55555)) # Connect to server
client.setblocking(False) # Prevent socket from waiting for input

W, H = 640, 480
FLAGS = 0

screen = pg.display.set_mode((W, H), FLAGS)
W, H = screen.get_size()

font = pg.font.SysFont("arial", 30)

text = ""

running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
running = False

try:
raw = client.recv(1024)
except BlockingIOError:
pass # No new data. Reuse old data
else:
text = raw.decode("utf-8") # New data has arrived. Use it

screen.fill((0, 0, 0))
img = font.render(text, True, (255, 255, 255))
r = img.get_rect(center=(W // 2, H // 2))
screen.blit(img, r)
pg.display.update()

This assumes a simple server script like this:

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server.bind(("localhost", 55555))
server.listen()

while True:
client, address = server.accept()
print("Connected to", address)
while True:
line = input("> ")
try:
client.send(line.encode("utf-8"))
except ConnectionError as e:
print(e)
print("Disconnecting")
client.close()
break

It will display whatever line of text you entered on the server in the center of the pygame window.


If you want t he reverse situation, where the server has a pygame window open, you can use these pieces of code:

server:

import socket

import pygame as pg

pg.init()

W, H = 640, 480
FLAGS = 0

screen = pg.display.set_mode((W, H), FLAGS)
W, H = screen.get_size()

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(("localhost", 55556))
server.listen(1)
server.setblocking(False)
client = None

font = pg.font.SysFont("arial", 30)

text = ""

clock = pg.time.Clock()
running = True
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
running = False
elif event.type == pg.VIDEORESIZE:
screen = pg.display.set_mode(event.size, FLAGS)
W, H = screen.get_size()
# Logic
dt = clock.tick()

if client is None:
try:
client, address = server.accept()
except BlockingIOError:
pass
else:
try:
raw = client.recv(1024)
except BlockingIOError:
pass
else:
text = raw.decode("utf-8")


# Render
screen.fill((0, 0, 0))
img = font.render(text, True, (255, 255, 255))
r = img.get_rect(center=(W // 2, H // 2))
screen.blit(img, r)

pg.display.update()
pg.display.set_caption(f"FPS: {clock.get_fps():.2f}")

client

import socket

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect(("localhost", 55556))

try:
while True:
line = input("> ")
try:
client.send(line.encode("utf-8"))
except ConnectionError as e:
print(e)
print("Disconnecting")
break
finally:
client.close()

If you want both to have pygames windows, I would suggest considering using multiple clients and one non-pygame server instead. But similar code should work anyway.

make client socket wait for server socket with Python

You can try something like this:

#!/usr/bin/env python
import pyaudio
import socket
import sys
import time


# Pyaudio Initialization
chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 10240

p = pyaudio.PyAudio()

stream = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
frames_per_buffer = chunk)

# Socket Initialization
host = ''
port = 50000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connected = False
while not connected:
try:
s.connect((host,port))
connected = True
except Exception as e:
pass #Do nothing, just try again

# Main Functionality
while 1:
data = stream.read(chunk)
s.send(data)
s.recv(size)

As for your second question: This should work on remote connections as well, since you bind to all interfaces with host='' Just make sure you portforward your router (only server needs to be port forwarded)

Python: fixed wait time for receiving socket data

The link with settimeout() was right. It raises a Exception when timeout.

Set a timeout on blocking socket operations. The value argument can be
a nonnegative floating point number expressing seconds, or None. If a
non-zero value is given, subsequent socket operations will raise a
timeout exception if the timeout period value has elapsed before the
operation has completed. If zero is given, the socket is put in
non-blocking mode. If None is given, the socket is put in blocking
mode.

You need to put your code in a try block, so that the Exception doesn't abort your program.

import socket.timeout as TimeoutException
# set timeout 5 second
clientsocket.settimeout(5)
for i in range(0,10):
sequence_number = i
start = time.time()
clientSocket.sendto("Ping " + str(i) + " " + str(start), server)
# Receive the client packet along with the address it is coming from
try:
message, address = clientSocket.recvfrom(1024)
except TimeoutException:
print("Timeout!!! Try again...")
continue
end = time.time()
if message != '':
print message
rtt = end - start
print "RTT = " + str(rtt)

Python socket wait for client connection

The socket.listen function is to be called once, because it sets the size of the connection queue.

Another function called socket.accept will block until connections are made. Modify your code like this:

mySocket = socket.socket()
mySocket.bind((host,port))
mySocket.listen(10)

while True:
client_socket, client_address = mySocket.accept() # blocking call
.... # do something with the connection

For more information, visit the docs.

Additionally, you'd want to pass the details of the client socket to the thread. The server socket isn't required. In effect, something like this:

def handle_client(client_socket, client_address):
.... # do something with client socket
client_socket.close()

...

while True:
client_socket, client_address = mySocket.accept()
T = threading.Thread(target=handle_client, args=(client_socket, client_address))
T.start()

You accept the connection in the main loop, then pass the client details to the thread for processing.



Related Topics



Leave a reply



Submit