i have a TCP Client on a Raspberry Pi connecting to a network Printer:
sock = socket.socket(sockwt.AF_INET, socket.SOCK_STREAM)
sock.settimeout(5)
sock.connect((ip,port))
My Problem ist now that the socket stays open when I unplug the network cable or turn off the printer.
And sending data does not fail -
sock.send(data)
always returns the correct number of bytes
So i tried to add a keep alive
sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 2)
but that changes nothing.
So why does the sock.send(data) not fail, when the server has died?
or: how can i make sock.send fail?
When I send data and the server has died, there should be no ACK. Why do I not get a information about that?
many thanks!
I am afraid that this is a TCP thing. You have a stream socket, and you asked for sending some bytes. A correct answer only means that the bytes could be sent but makes no guarantees for the peer receiving them. It is necessary because you could have a complex network with a number of switches and routers on the path.
Under normal circumstances, you should get an error at a time but possibly after sending some packets.
What could be done?
Some printer protocols have provision for commands close to Are You There? or Who Are You? that allow the client to ask the server for a message. That would be a robust way to make sure that the printer is ready.
Related
Im trying to write perl TCP server / python TCP client, and i have the such code now:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ("127.0.0.1", 9000)
sock.connect(server_address)
try:
message = unicode('Test')
sock.sendall(message)
data = sock.recv(1024)
print data
finally:
sock.close()
And i have noticed, that my TCP server (written in perl) is getting message not after sendall(message), but after close(). Server is working like an echo server, and sends data to client after getting a message. And that causes deadlock, server never gets a message, client never gets a response. What could be a problem? What is going to happen during close(), that message comes to server?
I'm going to hazard a guess that this is due to the server's implementation. There are many ways of writing an echo server:
receieve bytes in a loop (or async callback) until EOF; as the bytes are recieved (each loop iteration), echo them without any processing or buffering; when an EOF is found (the inbound stream is closed), close the outbound stream
read lines at a time (assume it is a text protocol), i.e. looking for CR / LF / EOF; when a line is found, return the line - when an EOF is found (the inbound stream is closed), close the outbound stream
read to an EOF; then return everything and close the outbound stream
If the echo server uses the first approach, it will work as expected already - so we can discount that.
For the second approach, you are sending text but no CR / LF, and you haven't closed the stream from client to server (EOF), so the server will never reply to this request. So yes, it will deadlock.
If it is the third approach, then again - unless you close the outbound stream, it will deadlock.
From your answer, it looks like adding a \n "fixes" it. From that, I conclude that your echo-server is line-based. So two solutions, and a third that would work in any scenario:
make the echo-server respond to raw data, rather than lines
add an end-of-line marker
close the outbound stream at the client, i.e. the client-to-server stream (many network APIs allow you to close the outbound and inbound streams separately)
Additionally: ensure Nagle is disabled (often called NO_DELAY) - this will prevent the bytes sitting at the client for a while, waiting to be composed into a decent sized packet (this applies to 1 & 2, but not 3; having Nagle enabled would add a delay, but will not usually cause a deadlock).
I'm trying to understand how udp messages are received. I have an external tool that sends data over udp every 1 second, and a simple python script that receives them something like this.
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(ip,port)
while True:
data, addr = sock.recvfrom(num)
I can receive the data, but if I change the code to
while True:
data, addr = sock.recvfrom(num)
time.sleep(10)
I am still receiving the same messages as before, just at a slower rate. I was expecting the messages sent during the 'time.sleep(10)' will be lost (which I understand will be most if not all the messages). Is there an internal storage that stores all the messages sent, whether or not the receiver is receiving them?
A Socket has a buffer that has nothing to do with python but with the OS.
So yes, the udp packets are just sitting there and waiting for the application to read them from the buffer to the application memory.
Of course this buffer is limited so if you wait too long tthe buffer will get full you will start to lose packets.
I'm currently working with python's socket library for the first time and i'm not very experienced with computer networking.
I'm able to connect to the server and the tcp handshake has happened as viewed by wireshark. After establishing a connection to the server(I have no control over the server), the connection stays open for a while, but after a small amount of time, the server sends a "FIN, ACK" and the connection is terminated. I'm trying to understand how I can keep this connection alive while the client is capable of reaching the server.
Looking at a tcp connection, it seems a packet can be sent every so often. Maybe a sort of keep alive message. I had thought using socket.send('hello') every 5 seconds in another thread would keep the connection with the server open, but I still get the "FIN, ACK" after some time.
In the documentation I found a setsockopt() but using this made no noticeable difference. I've tried client.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) both before and after the connection is made. I don't completely understand how this method is supposed to work, so maybe I used it incorrectly. There isn't much mention of this. I read somewhere about it being broken on windows. I don't know the truth in that.
What am I missing? The documentation for sockets doesn't seem to have anything about this unless I may have missed something.
import socket
import time
import threading
SERVER_IP = 'THE SERVER'
SERVER_PORT = SERVER_PORT
SOURCE_IP = socket.gethostname()
SOURCE_PORT = 57004
KEEP_ALIVE_INTERVAL = 5
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def keep_alive(interval):
data = 'hello'
while True:
client.send(data)
time.sleep(interval)
client.connect((SERVER_IP, SERVER_PORT))
t = threading.Thread(target=keep_alive, args = (KEEP_ALIVE_INTERVAL,))
t.start()
while True:
data = client.recv(1024)
if not data:
break
print data
client.close()
For enabling keep alive there is a duplicate question at How to change tcp keepalive timer using python script?
Keep in mind some servers and intermediate proxies forcibly close long lived connections regardless of keep alives being used or not, in which case you will see a FIN,ACK after X amount of time no matter what.
I have a fairly general question about best practice when using socket to communicate with remote hardware: should the socket be closed after each message is sent or left open?
To illustrate this question: I'm using python (and socket) to interface with a remote piece of hardware. Typically, I'll send a command to the device every 30 seconds or so, receive the reply and then wait ~ 30 seconds.
At present I'm doing:
# Open socket
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(10)
self.sock.connect((self.host_ip_address, self.port))
# Send Message
self.sock.send(my_command)
# Receive Reply
data = self.sock.recv(1024)
# Close socket
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
I wonder if this advisable, or should I simply leave the socket open for the duration of my session with the device (say ~ 1hr). Would this be robust?
Any tips / pointers welcomed thanks!
This is robust as long as you exchange data from time to time over your socket. If not, a Firewall/NAT can decide that the TCP connection is broken and stop routing the TCP packet.
I have a client which is creating packets and sending packets to a destination in a network which has been created using mininet. Now I am writing a python program at the destination to count the number of packets which has arrived. Now I know for sure that the packets are arriving at the destination (used tcpdump to verify it)
How do I go about it?
I thought of using this -
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
print s.recvfrom(5001)
But this seems to be slow. Is there any other alternative?
You want socket.IPPROTO_UDP for UDP packets, but otherwise, that's basically what you must do. No matter what other things you try, it's going to have to do those things.
Oh, and you'll want to do a socket.bind(('',PORT)) to bind it to the port you want it to listen on.