I am trying to decode data coming via TCP from labview. I want to send 4-bit header denoting the length followed by the message.
My LabVIEW sucessfully send the 4-bytes to the Python. And Python recieves b'\x00\x00\x00\x016' which clearly denotes a byte of information.
How do I then decode the command back to the integer length such that I can have an additional read to read in the rest of the message?
This is my python script:
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 9991))
server.listen(1)
while True:
conn, addr = server.accept()
messagelen = conn.recv(4)
print(messagelen)
bits = bytes.decode(messagelen)
print(bits)
server.close()
LabVIEW script
Are you sure your bytes you receive aren't b'\x00\x00\x00\x16'? If they are you can use the struct module to unpack.
import socket
import struct
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 9991))
server.listen(1)
while True:
conn, addr = server.accept()
bits = conn.recv(4)
messagelen = struct.unpack('>i', bits)[0]
print(messagelen)
server.close()
Related
I have this python server code here, which is waiting to receive a message digest and an encrypted message from a python client.
Clientside socket:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s=socket.socket()
s.connect((HOST, PORT))
s.sendall(transmit)
Server Side:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
print("\n Server is listing on port :", PORT, "\n")
fragments = []
#Execution stops here
with conn:
print(f"Connected by {addr}")
while True:
chunk = s.recv(4096)
if not chunk:
break
fragments.append(chunk)
arr = 'b'.join(fragments)
#Test to see if the array was being populated
print(arr[0])
I have tried the methods this stackOF post here, specifically above is the provided list method implementation as my client is sending a "packet" of information as a list encoded as a string
packet = [signeddigest, ciphertext]
transmit = str(packet)
transmit = transmit.encode()
s.sendall(transmit)
I have tested my client code on a different server codebase with the same localhost and port number, and that server was receiving the information, so there's something I'm missing in the server side.
The output from the test server was
File [b'HT\xb0\x00~f\xde\xc8G)\xaf*\xcc\x90\xac\xca\x124\x7f\xa0\xaa\ requested from ('127.0.0.1', 49817)
That "file" is the encoded string sent from my client to the test server. So I'm confident there's something wrong with my server implementation.
Further information:
When I run the server it listens, then I run the client.
python ClientTest.py
Please enter the message to send
Then the server side immediately closes the connection
line 23, in
chunk = s.recv(4096) OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and
(when sending on a datagram socket using a sendto call) no address was
supplied
You have a number of inconsistencies in your code:
while True:
chunk = s.recv(4096) # should be conn.recv(4096)
if not chunk:
break
fragments.append(chunk) # misaligned: you only append the empty chunk
arr = 'b'.join(fragments) # 'b' is an unicode string. You want b''
After fixing that to:
while True:
chunk = conn.recv(4096)
if not chunk:
break
fragments.append(chunk)
arr = b''.join(fragments)
arr will receive the sent data as soon as the client uses close or shutdown on its side of the socket.
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
conn is the connected socket, s is the listener socket.
chunk = s.recv(4096)
The error you get is because you are trying to read from the listener socket s, not from the connected socket conn:
line 23, in chunk = s.recv(4096) ... A request to send or receive data was disallowed because the socket is not connected ...
Im trying to send a messages from the server to the client
I tried deleting the .close and puting a while loop on print but it still doesn't won't to work
Client
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.connect((host, port))
while True:
print (s.recv(1024))
Server
import socket
s = socket.socket()
host = socket.gethostname()
port = 12345
s.bind((host, port))
s.listen(5)
while True:
c, addr = s.accept()
print ('Got connection from', addr)
x = str(input("ënter a message"))
data = x.encode()
c.send(data)
I expect the output to be 2 messages from the server but it is only sending 1 and then closing the connection
Switch your accept and while True: lines. Once you accept a connection, keep sending on the same connection.
Note that TCP is a streaming protocol. There is no concept of "messages", but just a bunch of bytes. If you send fast enough, such as:
c.send(b'abc')
c.send(b'def')
then recv(1024) could receive b'abcdef'. For more complex communication, you'll have to define a protocol and buffer recv until you are sure you have a complete message. A simple way in this case is read until you find a newline, or send a byte (or more) indicating the size of the total message before sending the actual message.
I copied the echo server example from the python documentation and it's working fine. But when I edit the code, so it wont send the data back to the client, the socket.recv() method doesn't return when it's called the second time.
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.close()
In the original version from the python documentation the while loop is slightly different:
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
Client's code:
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
data = s.recv(1024)
s.close()
print('Received', repr(data))
TCP sockets are streams of data. There is no one-to-one correlation between send calls on one side and receive calls on the other. There is a higher level correlation based on the protocol you implement. In the original code, the rule was that the server would send exactly what it received until the client closed the incoming side of the connection. Then the server closed the socket.
With your change, the rules changed. Now the server keeps receiving and discarding data until the client closes the incoming side of the connection. Then the server sends "ok" and closes the socket.
A client using the first rule hangs because its expecting data before it closes the socket. If it wants to work with this new server rule, it has to close its outgoing side of the socket to tell the server its done, and then it can get the return data.
I've updated the client and server to shutdown parts of the connection and also have the client do multiple recv's in case the incoming data is fragmented. Less complete implementations seem to work for small payloads because you are unlikely to get fragmentation, but break horribly in real production code.
server
import socket
HOST = ''
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(b'ok')
conn.shutdown(socket.SHUT_WR)
conn.close()
client
import socket
HOST = 'localhost'
PORT = 50007
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'Hello, world')
s.shutdown(socket.SHUT_WR)
data = b''
while True:
buf = s.recv(1024)
if not buf:
break
data += buf
s.close()
print('Received', repr(data))
The number of receive and send operations have to match because they are blocking. This is the flow diagram for your code:
Server listen
Client connect
Server receive (this waits until a message arrives at the server) [1]
Client send 'Hello world' (received by [1])
Server receive (because there was data received) [2]
Client receive [3]
Because the server and the client are blocked now, no program can continue any further.
The fix would be to remove the client's receive call because you removed the server's send call.
My client crash everytime it tries to connect to my python socket server. I dont know why but but my server seams to start up fine then when i start up my client it establishes a connection to the server but it crash direct. Im doing almost as what they say in py socket docs so im wondering if i have missed something or just staring blindly on something easy. Could any one help pls im using python3.4.
server.py
import socket
host = ''
port = 1010
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
print ("Connection from", addr)
while True:
databytes = conn.recv(1024)
if not databytes: break
print("Recieved: "+(databytes.decode('utf-8')))
response = input("Reply: ")
if response == "exit":
break
conn.sendall(response.encode('utf-8'))
conn.close()
client.py
import socket
host = '127.0.0.1'
port = 1010
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
print("Connected to "+(host)+" on port "+str(port))
initialMessage = input("Send: ")
s.sendall(initialMessage.encode('utf-8'))
while True:
data = s.recv(1024)
print("Recieved: "+(data.decode('utf-8')))
response = input("Reply: ")
if response == "exit":
break
s.sendall(response.encode('utf-8'))
s.close()
There are two issues in your server/client programs.
You server has two accept() calls, before the while loop and inside the while loop , this causes the server to actually wait for two connections before it can start receiving any messages from any client.
The socket.sendall() function takes in bytes not string , so you need to encode the string using some suitable encoding to convert it to bytes , before sending the data . Also , the function - socket.recv() - returns bytes . So you need to decode the bytes data (using the same encoding you used to encode when sending) , so that you can get the correct string back and it can be printed. A suitable encoding can be - utf-8 - but you can use any encoding of you choice.
An example of encoding a string and using sendall() func -
s.sendall(response.encode('utf-8'))
an example of decoding the string when receiving the data -
databytes = conn.recv(1024)
if not databytes: break
data = databytes.decode('utf-8')
You do not neccessarily need to store the decoded value in another variable, you can also directly call the .decode('utf-8') function when printing the data like - print("Recieved: "+(data.decode('utf-8'))) .
I just started coding in python I can't the encryption part of strings
I am trying to run this simple server client code
(The client is to run on raspberry-pi)
server :
#!/usr/bin/env python
import socket
server_socket = socket.socket()
server_socket.bind(('0.0.0.0', 8000))
server_socket.listen(0)
BUFFER_SIZE = 24
conn, addr = server_socket.accept()
print ('Got connection from', addr)
while 1:
data = conn.recv(BUFFER_SIZE)
if not data: break
print ("received data:", data)
conn.send(data) # echo
conn.close()
Client:(were I have the error)
import socket
client_socket = socket.socket()
client_socket.connect(("192.168.1.4", 8000))
BUFFER_SIZE = 1024
MESSAGE = "Hello, World!"
client_socket.send(MESSAGE)
data = client_socket.recv(BUFFER_SIZE)
client_socket.close()
print ("received data:", data)
The error here =:
File"c.py" line 9, in <module>
client_socket.send<MESSAGE>
typeError:'str' does not support the buffer interface
In python3 the interface to socket.send() changed to accept bytes instead of a string. See the difference between Python 3 docuentation and Python 2 documenation.
The solution is to encode the string before passing it to send() as follows:
client_socket.send(MESSAGE.encode())
In Python 3x strings are unicode, and they have to be encoded to bytes to send to a socket. The line:
client_socket.send(MESSAGE)
needs to be changed to:
client_socket.send(MESSAGE.encode('utf-8'))
On the server side you can decode data to get a string.