Non-blocking socket still continues to block on send() - python

I have a program interacting with two servers (all on localhost), which essentially forwards data from one server to the other.
I am trying to create a scenario where the server sending the initial data will close its connection to the middle-program because the server receiving the data has a very slow connection to the middle-program. The buffers of the middle-program should get filled, and it shouldn't be able to receive any data from the server sending data. As a result of this inactivity, the server sending data should timeout and close the connection, resulting in an in-complete data transfer.
I am trying to do it in the following way:
Program at server sending the data
import socket
interval_sec = 3
TCP_KEEPALIVE = 0x10
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, TCP_KEEPALIVE, interval_sec)
sock.bind(('', 9000))
sock.listen(5)
while True:
conn, addr = sock.accept()
f = open('test.txt', 'r')
file_data = f.read(1024)
while (file_data):
conn.send(file_data)
file_data = f.read(1024)
f.close()
print "sent"
Middle program forwarding the data
import socket
import select
import time
import struct
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
recv_timeout = 2
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, struct.pack('LL', recv_timeout, 0))
total_data=[]
total_sent=0;
data=0;
sock.connect(('localhost', 9000))
sock2.connect(('localhost', 8001))
sock2.setblocking(0)
sock.setblocking(0)
j=0
while 1:
read, write, errors = select.select([sock], [sock2], [], 2)
if read:
data=sock.recv(1024, socket.MSG_DONTWAIT)
total_data.append(data)
#time.sleep(10)
if write:
if data:
try:
data_sent=sock2.send(data, socket.MSG_DONTWAIT)
total_sent+=data_sent
data=data[data_sent:]
print data_sent
except socket.error, e:
if e.errno != errno.EAGAIN:
raise e
else:
print "Not writable"
Program at server receiving the data
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', 8001))
sock.listen(5)
while True:
conn, addr = sock.accept()
with open('received_file', 'wb') as f:
while True:
file_data = conn.recv(100)
print('receiving data...')
if not file_data:
break
f.write(file_data)
f.close()
conn.close()
The problem I'm facing is that, the middle-program's sockets are blocking although they should be acting as non-blocking.
Are my programs fundamentally wrong, and I'm missing the whole point or do I need to make some minor tweaks?
Thanks :)

Related

Hello everyone, I am trying to receive all the data coming from a server but the loop does not stop

So here is the code hangs on the while loop.
client.py:
import socket
ip = "127.0.0.7"
port = 65000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((ip, port))
while True:
file = input("Filename:")
s.sendall(file.encode())
b = b""
while True:
data = s.recv(4096)
if not data:
break
b+=data
with open(file, "wb") as f:
f.write(donne)
break
server.py:
import socket
import os
ip = "127.0.0.7"
port = 65000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((ip, port))
s.listen(5)
conn, addr = s.accept()
while True:
receive = conn.recv(1024).decode()
if os.path.exists(receive):
with open(receive, "rb") as f:
data = f.read()
conn.sendall(data)
break
else:
print("File not found")
The problem is with the client code.
I would like to receive all the data and write them to a file but the loop in client.py does not stop.

How to continuously send images from raspberry to pc without delay?

I'm trying to send webcam captured images from pi to pc, but while using socket programming for it, i'm getting a significant amount of delay (about 5-6 seconds per image). Am I doing something wrong over here? Is there a way to reduce this delay or any other better technique to send the data to pc with minimum delay?
Server side:
import socket
port = 60000
s = socket.socket()
host = ""
s.bind((host, port))
s.listen(5)
print('Server listening....')
while True:
conn, addr = s.accept()
print 'Got connection from', addr
data = conn.recv(1024)
print('Server received', repr(data))
filename='mytext.txt'
f = open(filename,'rb')
l = f.read(1024)
while (l):
conn.send(l)
print('Sent ',repr(l))
l = f.read(1024)
f.close()
print('Done sending')
conn.send('Thank you for connecting')
conn.close()
Client:
import socket # Import socket module
import time
s = socket.socket() # Create a socket object
host = "192.1.1.1" #Ip address that the TCPServer is there
port = 60000 # Reserve a port for your service.
s.connect((host, port))
s.send("Hello server!")
with open('received_file.png', 'wb') as f:
print 'file opened'
start = time.time()
while True:
# print('receiving data...')
data = s.recv(1024)
# print('data=%s', (data))
if not data:
break
# write data to a file
f.write(data)
print(time.time() - start)
f.close()
print('Successfully get the file')
s.close()
print('connection closed')

Python - Send Integer or String to Spark-Streaming

I can send my data through CSV file. First, write my random numbers into CSV file then send it, but is it possible to send it directly?
my socket code:
import socket
host = 'localhost'
port = 8080
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
while True:
print('\nListening for a client at',host , port)
conn, addr = s.accept()
print('\nConnected by', addr)
try:
print('\nReading file...\n')
while 1:
out = "test01"
print('Sending line', line)
conn.send(out)
except socket.error:
print ('Error Occured.\n\nClient disconnected.\n')
conn.close()
spark streaming code:
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
sc = SparkContext("local[2]","deneme")
ssc = StreamingContext(sc, 10)
socket_stream = ssc.socketTextStream("localhost",8080)
random_integers = socket_stream.window( 30 )
digits = random_integers.flatMap(lambda line: line.split(" ")).map(lambda digit: (digit, 1))
digit_count = digits.reduceByKey(lambda x,y:x+y)
digit_count.pprint()
ssc.start()
This is because socket blocks sending the data and never moves on. The most basic solution is to send some amount of data and close the connection:
import socket
import time
host = 'localhost'
port = 50007
i = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
try:
while True:
conn, addr = s.accept()
try:
for j in range(10):
conn.send(bytes("{}\n".format(i), "utf-8"))
i += 1
time.sleep(1)
conn.close()
except socket.error: pass
finally:
s.close()
To get something more interesting check non-blocking mode with timeouts.

Python, I want to make Multiple Connection Chatting Program

I coded chatting program with socket module.
(Python)
and I saw perfect send and get data.
But I found a problem.
This is my Server.py
import socket
import threading
HOST = '127.0.0.1'
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print(addr)
def sendmsg():
while True:
data = input()
data = data.encode("utf-8")
conn.send(data)
conn.close()
def getmsg():
while True:
data = conn.recv(1024)
if data is None:
break
else:
data = data.decode("utf-8", "ignore")
print(data)
conn.close()
threading._start_new_thread(sendmsg, ())
threading._start_new_thread(getmsg, ())
while True:
pass
Just on Client can connect with server.
I want to make multiple connection.
So I changed value of s.listen(1) to s.listen(2)
but It doesn't work.
Help me TT
This is client.py
import socket
import threading
HOST = "127.0.0.1"
PORT = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
def sendMsg():
while True:
data = input()
s.sendall(str.encode(data))
s.close()
def getMsg():
while True:
data = s.recv(1024)
data = data.decode("utf-8")
print(data)
s.close()
threading._start_new_thread(sendMsg, ())
threading._start_new_thread(getMsg, ())
while True:
pass
Thank you.

Non-Blocking error when adding timeout to python server

I am writing a simple TCP server in python, and am trying to input a timeout. My current code:
import socket
def connect():
HOST = '' # Symbolic name meaning the local host
PORT = 5007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
s.settimeout(5)
conn, addr = s.accept()
print 'Connected by', addr
return conn
conn = connect()
while 1:
data = conn.recv(1024)
if not data: break
print data
conn.close()
Issue is when I try to connect I get an error at data = conn.recv(1024)
error: [Errno 10035] A non-blocking socket operation could not be completed immediately
Code works without the timeout.
You can turn on blocking:
# ...
conn.setblocking(1)
return conn
# ...
Try to set the timeout on the socket and the blocking on the connection. Like this:
import socket
def connect():
HOST = '' # Symbolic name meaning the local host
PORT = 5007 # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
s.bind((HOST, PORT))
s.listen(1)
return s
s = connect()
while 1:
conn, addr = s.accept()
print 'Connected by', addr
conn.setblocking(1)
data = conn.recv(1024)
conn.close()
if not data: break
print data
s.close()
Ran into the same problem 30 minutes ago. Found a simple non-elegant work around...if you give the socket time to breathe by doing time.sleep(1), catching the 10035 error and doing a retry it works. I'm using 2.7.5...maybe this is a bug that got fixed. Not real sure.
Code sample...please understand this is very simplistic test code I use (only recv 1 byte at a time).So where 's' is the socket with a 10s timeout and 'numbytes' is number of bytes I need...
def getbytes(s,numbytes):
din = ''
socketerror10035count = 0
while True:
try:
r = s.recv(1).encode('hex')
din += r
if len(din)/2 == numbytes:
print 'returning',len(din)/2, 'bytes'
break
except socket.timeout as e:
din = 'socket timeout'
break
except socket.error as e:
if e[0] == 10035 and socketerror10035count < 5:
socketerror10035count = socketerror10035count +1
time.sleep(1)
else:
din = 'socket error'
break
except:
din = 'deaddead'
break
return din
For Python 3 and above, the above code which references e as a scriptable object will need to be changed to "e.errno". And, of course the print statements require parenthesis around the arguments.
Additionally, you may want to change the "except socket.error as e:" line to "except BlockingIOError as e:". However, the code works as is under Python 3.8.5 on Windows.

Categories

Resources