socket recv not returning - python

I can't understand why socket recv doesn't return. I have a client application that send string to a server. The client is executed in a terminal. This is the code
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "Enter client sender"
try:
client.connect((target, port))
if len(buffer):
client.send(buffer)
while True:
print "Enter loop"
recv_len = 1
response = ""
while recv_len:
print "Enter loop 2"
data = client.recv(4096)
print "Afer recv"
recv_len = len(data)
print recv_len
response += data
if recv_len < 4096:
break
print response,
buffer = raw_input("")
buffer += "\n"
client.send(buffer)
except:
print "[*] Exception Exiting"
client.close()
But the "After recv" label is never reached. Why? Can you help me? What is wrong?

Your code is generally correct, although bufferis a built-in type and you should avoid using it as a variable name (but it will still work if you do).
On a blocking socket (the default state), recv will block until there is some data available for reading. Make sure the other endpoint is sending (and flushing to the socket) a response.
You might find tcpdump or Wireshark useful to see the packets actually being transmitted. Also, I suggest you use nc or a similar generic TCP socket tool to debug this. E.g., nc -4 -l localhost PORT (-4 because your AF_INET implies IPv4).

Related

How to fix socket.timeout and receiving data

I write that Program a while ago and now it stopped working. Every time I run it say "timed out". This Error also occurs when I set the timeout higher for example to 10sec.
import sys
import socket
def traceroute(dest_addr, max_hops=30, timeout=0.2):
proto_icmp = socket.getprotobyname('icmp')
proto_udp = socket.getprotobyname('udp')
port = 33434
for ttl in range(1, max_hops+1):
rx = socket.socket(socket.AF_INET, socket.SOCK_RAW, proto_icmp)
rx.settimeout(timeout)
rx.bind(('', port))
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, proto_udp)
tx.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
tx.sendto(bytes('', 'utf-8'), (dest_addr, port))
try:
data, curr_addr = rx.recvfrom(512)
curr_addr = curr_addr[0]
except socket.error as err:
print (err)
curr_addr = None
finally:
rx.close()
tx.close()
yield curr_addr
if (curr_addr == dest_addr):
break
if __name__ == "__main__":
dest_name = "www.google.de"
dest_addr = socket.gethostbyname(dest_name)
print("traceroute to %s (%s)" % (dest_name, dest_addr))
for i, v in enumerate(traceroute(dest_addr)):
print("%d\t%s" % (i+1, v))
presumably some router between your computer and Google isn't sending an ICMP "host unreachable" message which your code is unconditionally waiting for.
the code you've posted is very "fragile" and it'll tend to break in weird and wonderful ways on the internet. e.g. the example here is that you always wait for an ICMP message immediately after sending your UDP packet, but you might also get a UDP packet back (if the port happens to be open) or nothing back if a router in the middle is silently dropping packets on TTL expiry.
I'd suggest using select (or similar) to handle waiting for multiple (i.e. both UDP and ICMP) sockets concurrently, or you could use an async library to keep track of everything

Python HL7 Listener socket message acknowledgement

I am trying to create HL7 listener in python. I am able to receive the messages through socket , but not able to send valid acknowledgement
ack=u"\x0b MSH|^~\\&|HL7Listener|HL7Listener|SOMEAPP|SOMEAPP|20198151353||ACK^A08||T|2.3\x1c\x0d MSA|AA|153681279959711 \x1c\x0d"
ack = "MSH|^~\&|HL7Listener|HL7Listener|SOMEAPP|SOMEAPP|20198151353||ACK^A08||T|2.3 \r MSA|AA|678888295637322 \r"
ack= bytes(ack,'utf-8')
Python code :
def listner_hl7():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((socket.gethostname(), 4444))
except Exception as e:
print(str(e))
s.listen(5)
while True:
clientSocket, addr = s.accept()
message = clientSocket.recv(2048)
id = (str(message.splitlines()[0]).split('|')[9])
print('received {} bytes from {}'.format(
len(message), addr))
print('sending acknowledgement: ')
ack = b"\x0b MSH|^~\\&|HL7Listener|HL7Listener|SOMEAPP|SOMEAPP|20198151353||ACK^A08||T|2.3\x1c\x0d MSA|AA|" + bytes(
id, 'utf-8') + b" \x1c\x0d"
clientSocket.send(ack)
I think your complete acknowledge is not being sent. You are using clientSocket.send(ack).
Use clientSocket.sendall(ack) instead.
Please refer to this answer from #kwarunek for more details.
socket.send is a low-level method and basically just the C/syscall method send(3) / send(2). It can send less bytes than you requested, but returns the number of bytes sent.
socket.sendall is a high-level Python-only method that sends the entire buffer you pass or throws an exception. It does that by calling socket.send until everything has been sent or an error occurs.
If you're using TCP with blocking sockets and don't want to be bothered by internals (this is the case for most simple network applications), use sendall.
try adding enter in front of MSA|AA in the \n syntax I think it works

s.sendall doesn't work inside a thread in python

I'm trying to develop a chat program in python. I want it to have multiple clients so I'm using threading to handle this. However when I try to send the message to all connected clients, the server only sends it to the client which sent the message. I'm not sure if I'm just missing something obvious but here is the code for the server:
import socket
from thread import *
host = '192.168.0.13'
port = 1024
users = int(input("enter number of users: "))
def clienthandler(conn):
while True:
data = conn.recv(1024)
if not data:
break
print data
conn.sendall(data)
conn.close()
serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversock.bind((host, port))
serversock.listen(users)
for i in range(users):
conn, addr= serversock.accept()
print 'Connected by', addr
start_new_thread(clienthandler, (conn,))
And here is the code for the client:
import socket
host = '192.168.0.13'
port = 1024
usrname = raw_input("enter a username: ")
usrname = usrname + ": "
clientsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
clientsock.connect((host, port))
while True:
x = raw_input('You: ')
x = usrname + x
clientsock.sendall(x)
data = clientsock.recv(1024)
print data
The "all" in sendall means that it sends all of the data you asked it to send. It doesn't mean it sends it on more than one connection. Such an interface would be totally impractical. For example, what would happen if another thread was in the middle of sending something else on one of the connections? What would happen if one of the connections had a full queue?
sendall: Send data to the socket. The socket must be connected to a remote socket. The optional flags argument has the same meaning as for recv() above. Unlike send(), this method continues to send data from string until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully sent. -- 17.2. socket
You can try by pulling up the list of users, and iterating through it, and doing an individual send of the same message, though, unless you are the administrator and want to broadcast a warning, this functionality would be pretty mundane.

What data is required and available for persistant http connections

I'm trying to send a stream of images across http using a "persistent" connection. I have keep-alive in the header and so does the client (firefox) but I dont know how to send the second request or how to wrap it.
I've read the rfc. I've also wiresharked the connection while looking at a streaming service just like the one I'm trying to duplicate. I dont see any http messages going back and forth as the data is streamed (mjpg streamer)
So My question is this, what is required to send back to client in a http persistent connection ? If I just send fully formed http responses or just jpg data the client disconnects. If I wait for the client to send more data before sending the second image the client never sends anything.
import socket
import sys
import time
import binascii
from thread import *
HOST = '' # Symbolic name meaning all available interfaces
PORT = 9998 # Arbitrary non-privileged port
in_file = open("picture.jpg", "rb") # opening for [r]eading as [b]inary
testJpg = in_file.read() # if you only wanted to read 512 bytes, do .read(512)
in_file.close()
in_file = open("picture2.jpg", "rb") # opening for [r]eading as [b]inary
testJpg2 = in_file.read() # if you only wanted to read 512 bytes, do .read(512)
in_file.close()
OddNumber = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
#Bind socket to local host and port
try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
#Start listening on socket
s.listen(10)
print 'Socket now listening'
#Function for handling connections. This will be used to create threads
def clientthread(conn):
global OddNumber, testJpg, testJpg2
OddNumber = 0
# get data from the client (assume its a http get request)
data = conn.recv(1024)
print("\r\n Got1: "+str(len(data)))
#time.sleep(.05)
while OddNumber < 30:
# create a new reply
reply = "HTTP/1.0 200 OK\r\n"
reply += "Server: MJPG-Streamer/0.2\r\n"
reply += "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"
reply += "Pragma: no-cache\r\n"
reply += "Content-type: image/jpeg\r\n"
# add in the content len
if OddNumber % 2 == 0:
reply += "Content-Length: "+str(len(testJpg))+"\r\n"
else:
reply += "Content-Length: "+str(len(testJpg2))+"\r\n"
# add the keep alive portion
reply += "Connection: Keep-Alive\r\n"
# I think we need this
reply += "\r\n"
# I use this toggle to switch between different images so if it does "stream" i'll be able to see it
# flipping these images
if OddNumber % 2 == 0:
reply += testJpg
else:
reply += testJpg2
# after the image
reply += "\r\n"
conn.sendall(reply)
OddNumber += 1
print("\r\n OddNum: "+str(OddNumber))
data = conn.recv(1024)
print("\r\n Got1: "+str(len(data)))
print(str(data))
#time.sleep(.05)
#came out of loop
conn.close()
#now keep talking with the client
while 1:
#wait to accept a connection - blocking call
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
start_new_thread(clientthread ,(conn,))
s.close()
Apart from that I'm wondering if the persistent connection will even work for me. I'm developing a embedded device that is hosting the images, similar to a ipcamera. But I need to be able to send different URL's back to the device while it is sending me images. Is this possible on the same port ?
Someone requested I show whats in my http response. It is what you see in the python script. Its a valid http response and it works fine if I set
Connection: Keep-Alive\r\n"
to
Connection: close\r\n"
I guess my question is, what do you have to do in a persistent connection. Will the client send more "get" requests or is the server expected to stream some data ? At least firefox only sends one "get" request and then I send the response with a image but then what has to happen next to keep it going ?
Thanks for all the help so far.
I'm afraid that's because you use the same socket object in both client and server. Can you separate your code into two files? One file for server and the other for client (means your clientthread function).
In HTTP, when client get an HTTP response with 'keep-alive', it will hold TCP connection no matter what kinds of data you send.

Send/receive Packets with TCP sockets

Recently, I managed to create sockets on my PC and my Raspberry Pi to enable communication between both devices. Currently, the client is able to automatically send messages to the server. I was wondering, if it is possible to modify the scripts to send tcp data packets instead of purely text messages, as I would very much like to control the raspberry pi using my PC in the future without having the need to ssh/etc.
I've looked at some examples, but as I don't have much experience in writing my own scripts/codes, I'm not very sure how to go about doing this. I would appreciate if someone could guide me in the right direction with explanation and some examples if possible.
Anyway here is the server/client script I'm running at the moment:
Client:
import socket
import sys
import struct
import time
#main function
if __name__ == "__main__":
if(len(sys.argv) < 2) :
print 'Usage : python client.py hostname'
sys.exit()
host = sys.argv[1]
port = 8888
#create an INET, STREAMing socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
print 'Socket Created'
try:
remote_ip = socket.gethostbyname( host )
s.connect((host, port))
except socket.gaierror:
print 'Hostname could not be resolved. Exiting'
sys.exit()
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
#Send some data to remote server
message = "Test"
try :
#Set the whole string
while True:
s.send(message)
print 'Message sent successfully'
time.sleep(1)
print 'Sending...'
except socket.error:
#Send failed
print 'Send failed'
sys.exit()
def recv_timeout(the_socket,timeout=2):
#make socket non blocking
the_socket.setblocking(0)
#total data partwise in an array
total_data=[];
data='';
#beginning time
begin=time.time()
while 1:
#if you got some data, then break after timeout
if total_data and time.time()-begin > timeout:
break
#if you got no data at all, wait a little longer, twice the timeout
elif time.time()-begin > timeout*2:
break
#recv something
try:
data = the_socket.recv(8192)
if data:
total_data.append(data)
#change the beginning time for measurement
begin=time.time()
else:
#sleep for sometime to indicate a gap
time.sleep(0.1)
except:
pass
#join all parts to make final string
return ''.join(total_data)
#get reply and print
print recv_timeout(s)
s.close()
Server:
import socket
import sys
from thread import *
HOST = '' # Symbolic name meaning all available interfaces
PORT = 8888
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print 'Socket created'
try:
s.bind((HOST, PORT))
except socket.error , msg:
print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
sys.exit()
print 'Socket bind complete'
s.listen(10)
print 'Socket now listening'
#Function for handling connections
def clientthread(conn):
#Sending message to connected client
conn.send('Welcome to the server. Receving Data...\n') #send only takes string
#infinite loop so that function do not terminate and thread do not end.
while True:
#Receiving from client
data = conn.recv(1024)
reply = 'Message Received at the server!\n'
print data
if not data:
break
conn.sendall(reply)
conn.close()
#now keep talking with the client
while 1:
#wait to accept a connection
conn, addr = s.accept()
print 'Connected with ' + addr[0] + ':' + str(addr[1])
#start new thread
start_new_thread(clientthread ,(conn,))
s.close()
socket.socket(socket.AF_INET, socket.SOCK_STREAM) already creates a connection that provides a reliable stream of bytes between two machines. This uses TCP, which is on top of IP and Ethernet. The latter two are package-based, while TCP creates a stream of continuous bytes on top of it. It also adds some error checking and error correction, so it is pretty reliable.
I honestly don't understand what you want to achieve with what you call "send packets". What you don't want to do is to create an implementation of TCP yourself, as that's a non-trivial task, so sending RAW packets is out. In general, even using TCP is already relatively low-level and should be avoided unless really necessary.
Using e.g. ZeroMQ you get a message-based interface that does all the transmission for you. It does so on top of TCP (or other transports) and adds more error correction for e.g. disconnects. There, you also have something like "packets", but those are independent of how many TCP or IP packets were required to send it underneath. If you don't want to implement a specific protocol, I'd suggest you use this framework instead of lowlevel TCP sockets.
Another simple alternative is to use HTTP, for which there is also existing code in Python. The downside is that it is always one side that initiates some communication and the other side only replies. If you want some kind of active notification, you either have to poll or use hacks like delaying an answer.
You are already sending data packets - those packets juts happen to contain text data at the moment. Try looking into pickle in the standard libraries and into pyro.

Categories