Reputation: 101
I need to send a string to a particular port on localhost using python.
I can achieve this by using socat on the command line like such:
cat <text file containing string to send> | socat stdin tcp-connect:127.0.0.1:55559
I don't want to run the socat command as a subcommand so I'd like to know how to get this working using a python module.
My attempts at using sockets failed. Below is a script I was using which wasn't achieving the desired effect.
import socket
HOST, PORT = "127.0.0.1", 55559
jsonString = '{"name":"VideoStreamStatus","parameters":{"name":"video_0_0"}}'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# Connect to server and send data
print "Attempting connection"
sock.connect((HOST, PORT))
print "Sending json string"
sock.sendall(jsonString)
print "String sent"
finally:
sock.close()
print "Sent: {}".format(jsonString)
The python script was executing without any errors but there wasn't any effect on the process which was receiving the socat data. Python script output below:
Attempting connection
Sending json string
Sent: {"name":"VideoStreamStatus","parameters":{"name":"video_0_0"}}
Is there something I'm doing wrong in the socket script or is there a different method I can use in Python? I'd appreciate any advice. Thanks.
Edit: The server I'm trying to send strings to is part of a C++ program using boost asio acceptor to listen for tcp connections on a specific address and port.
Upvotes: 6
Views: 9953
Reputation: 101
Turned out to be something really simple. The string I was sending using socat (which the server was receiving and processing successfully) had a newline on the end of it. The string I was sending over the python socket didn't have a new line. After adding a new line to the end of the python script the server receives the string as expected.
I only realised that there was a newline after one and not the other after running a python server script listening on a different port and sending the string using both methods.
Upvotes: 2
Reputation: 149145
You shall never close a socket immediately after writing into a socket: the close could swallow still unsent data.
The correct workflow is what is called a graceful shutdown:
So the finally
part becomes:
finally:
try:
sock.shutdown(socket.SHUT_WR)
while True:
dummy = sock.recv(1024)
if len(dummy) == 0: break
finally:
sock.close()
Upvotes: 0
Reputation: 168806
According to the socat man page,
When one channel has reached EOF, the write part of the other channel is shut down. Then, socat waits
timeout
seconds before terminating. Default is 0.5 seconds.
Perhaps you need to defer your close by 0.5 seconds, like so:
finally:
#sock.close()
sock.shutdown(socket.SHUT_WR)
time.sleep(0.5)
sock.close()
Or, perhaps you need to absorb the server's shutdown message, like so:
finally:
#sock.close()
sock.shutdown(socket.SHUT_WR)
sock.recv(999999)
sock.close()
Upvotes: 0