I'm new to python programming. I want to create a simple TCP server working with an esp32. The idea of this is to send command data = '{\"accel\",\"gyro\",\"time\":1}' to esp32 via socket and then wait around 10ms for reply from esp32. I tried many examples but nothing works. ESP32 gets my message from this program but I can't receive message from esp32.
import socket
# bind all IP address
HOST = '192.168.137.93'
# Listen on Port
PORT = 56606
#Size of receive buffer
localhost=('0.0.0.0', 56606)
BUFFER_SIZE = 1024
# Create a TCP/IP socket
data = '{\"accel\",\"gyro\",\"time\":1}'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the host and port
s.connect((HOST, PORT))
# send data to server
s.send(bytearray(data, 'utf-8'))
s.serve_forever()
print('Listen for incoming connections')
sock.listen(1)
while True:
client, addr = s.accept()
while True:
content = client.recv(1024)
if len(content) ==0:
break
else:
print(content)
print("Closing connection")
client.close()
I tried more and tried to use other code(see below). Now I get message back but on other port(I can track it by wireshark)
import socket
# Ip of local host
HOST = '192.168.137.93'
# Connect to Port
PORT = 56606
#Size of send buffer
BUFFER_SIZE = 4096
# data to sent to server
message = '{\"accel\",\"gyro\",\"time\":1}'
# Create a TCP/IP socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to server
s.connect((HOST, PORT))
# send data to server
s.send(bytearray(message, 'utf-8'))
# Receive response from server
data = ""
while len(data) < len(message):
data = s.recv(BUFFER_SIZE)
# Close connection
print ('Server to Client: ' , data)
s.close()
I don't use both of these codes together.
Any hints?
Related
I am building a server to send data to the client in Python. I would like to continuously send the time until the client closes the connection. So far, I have done :
For the server:
import socket
from datetime import datetime
# take the server name and port name
host = 'local host'
port = 5001
# create a socket at server side
# using TCP / IP protocol
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# bind the socket with server
# and port number
s.bind(('', port))
# allow maximum 1 connection to
# the socket
s.listen(1)
# wait till a client accept
# connection
c, addr = s.accept()
# display client address
print("CONNECTION FROM:", str(addr))
dateTimeObj = str(datetime.now())
print(dateTimeObj)
c.send(dateTimeObj.encode())
# disconnect the server
c.close()
For the client:
import socket
# take the server name and port name
host = 'local host'
port = 5001
# create a socket at client side
# using TCP / IP protocol
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# connect it to server and port
# number on local computer.
s.connect(('127.0.0.1', port))
# receive message string from
# server, at a time 1024 B
msg = s.recv(1024)
# repeat as long as message
# string are not empty
while msg:
print('Received date :' + msg.decode())
msg = s.recv(1024)
# disconnect the client
s.close()
How can I modify the server to continously send the current date? At the moment, the server is just sending one date and closing the connection.
you need to use While True loop.
import socket
from datetime import datetime
# take the server name and port name
host = 'local host'
port = 5001
# create a socket at server side
# using TCP / IP protocol
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# bind the socket with server
# and port number
s.bind(('', port))
# allow maximum 1 connection to
# the socket
s.listen(1)
# wait till a client accept
# connection
while True:
c, addr = s.accept()
# display client address
print("CONNECTION FROM:", str(addr))
dateTimeObj = str(datetime.now())
print(dateTimeObj)
c.send(dateTimeObj.encode())
# disconnect the server
c.close()
client:
import socket
# take the server name and port name
host = 'local host'
port = 5001
# create a socket at client side
# using TCP / IP protocol
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
# connect it to server and port
# number on local computer.
s.connect(('127.0.0.1', port))
# receive message string from
# server, at a time 1024 B
while True:
msg = s.recv(1024)
# repeat as long as message
# string are not empty
while msg:
print('Received date :' + msg.decode())
msg = s.recv(1024)
# disconnect the client
s.close()
I am trying to establish TCP connection on the client-side using socket. The first part seem to work fine:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
HOST = '127.0.0.1' # The server's hostname or IP address
PORT = 1234 # The port used by the server
s.connect((HOST, PORT))
Now for the send() the server-side requires:
Once a client is connected it needs to send the following string in order to send a marker: <TRIGGER>XXXX</TRIGGER>In our case XXX is defined as var.trigger
When I write it like s.send(bytes (var.trigger)) it runs with no errors, however, I guess because it is not defined as a string the server does not recognize it.
Thank you in advance
p.s. I don't code in Python so it can be something very basic that I am missing here.
I am also fairly new to python sockets, but I tried this and it worked. My guess is that you need to wait for the data to be sent (on your server side) with something like this:
while True: # Infinite loop
data = conn.recv(1024) # 1024 = number of bytes to be recieves
if not data: # If data is false, or an empty string/list, etc.
break
print("Recieved:", data.decode('utf-8')) # Printing recieved data
The full code is as follows:
import socket
# ========== SERVER ==========
def server():
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) # Setting up socket
HOST = '127.0.0.1' # Localhost
PORT = 65432
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept() # Accepting connection
print("========== SERVER ==========")
print("Connected by:", addr)
while True: # Infinite loop
data = conn.recv(1024) # 1024 = number of bytes to be recieves
if not data: # If data is false, or an empty string/list, etc.
break
print("Recieved:", data.decode('utf-8')) # Printing recieved data
# ========== CLIENT ==========
def client():
s = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
HOST = '127.0.0.1' # Localhost
PORT = 65432
s.connect((HOST, PORT)) # Connecting to server
print("========== CLIENT ==========")
var = 'XXXX' # Replace with actual variable
s.sendall(f"<TRIGGER>{var}<TRIGGER>".encode('utf-8')) # Sending trigger message
print(f"Sent: <TRIGGER>{var}<TRIGGER>")
My socket sends the first message but nothing afterward.
The output in the server:
What do you want to send?
lol
The client receives:
From localhost got message:
lol
And then it doesn't want to send anything else.
I don't get the what do you want to send printed anymore.
My code:
server.py file:
#!/usr/bin/python3
import socket
# create a socket object
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# get local machine name
host = socket.gethostname()
print ("got host name:", host)
port = 9996
print("connecting on port:", port)
# bind to the port
serversocket.bind((host, port))
print("binding host and port")
# queue up to 5 requests
serversocket.listen(5)
print("Waiting for connection")
while True:
clientsocket, addr = serversocket.accept()
msg = input("what do you want to send?\n")
clientsocket.send(msg.encode('ascii'))
client.py file:
#!/usr/bin/python3
import socket # create a socket object
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # get local machine
# name
host = socket.gethostname()
port = 9996 # connection to hostname on the port.
s.connect((host, port)) # Receive no more than 1024 bytes
while True:
msg = s.recv(1024)
print(msg.decode("ascii"))
The client only connects once (OK) but the server waits for an incoming connection every start of the while loop.
Since there are no more connection requests by a client, the server will freeze on the second iteration.
If you just want to handle a single client, move clientsocket, addr = serversocket.accept() before the while loop. If you want to handle multiple clients, the standard way is to have the server accept connections inside the while loop and spawn a thread for each client.
You can also use coroutines, but that may be a bit overkill if you are just starting out.
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.
How do I get a response from the server?
Client side:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
data_c = input()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port))
print( data_c )
print( c.recv(1024).decode('utf-8'))
SERVER side:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
print(s.recv(1024).decode('utf-8'))
I can send a message from the server that the client will receive, but can not seem to get communication (like an ACK.) to make it back to the server.
(yes UDP is not a good way to be doing this i'm pretty sure, but that was a specific for the project)
for question 1: to send the ACK, you could replicate what you have in the reverse direction.
Since UDP is connection-less you don't know beforehand you receive a packet where the packet will come from, so you have to use recvfrom to get both the packet and the peer (address/port) the packet came from. Then you have to use that address to send data back.
What you're doing now in your client (but what really looks like the server) in the loop is send the same data over and over to itself. Instead in the loop you should receive packets using the previously mentions recvfrom then send replies to the peer you received the packet from.
So something like the following pseudo code
while True:
peer = recvfrom(...)
sendto(..., peer)
After many attempts to get a simple acknowledgment reply from my server this did it.
Beyond literally starting completely over each round, the time.sleep(.1) function was the only missing key. It allowed the server and client both time to close the current socket connection so that there was not an error of trying to bind multiple bodies to a single location or something.
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
Working result:
#SERVER
import socket
import time
host = "localhost"
port = 5454
data_s = "ACKNOWLEDGMENT"
while 1:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((host, port))
received = print("Client: " + s.recv(1024).decode('utf-8')) #waiting to receive
s.close
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
s.sendto(bytes(data_s, 'utf-8'),(host,port)) #sending acknowledgment
print("Server: " + data_s)
s.close # close out so that nothing sketchy happens
time.sleep(.1) # the delay keeps the binding from happening to quickly
Server Command Window:
>>>
Client: hello
Server: ACKNOWLEDGMENT
Client:
#CLIENT
import socket
import time
host = "localhost"
port = 5454
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while 1:
data_c = input("Client: ")
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.sendto(bytes(data_c, 'utf-8'),(host,port)) #send message
c.close
# time.sleep()
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
c.bind((host, port))
print("Server: " + c.recv(1024).decode('utf-8')) # waiting for acknowledgment
c.close
c = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
time.sleep(.1)
Client Command Window:
>>>
Client: hello
Client: hello
Server: ACKNOWLEDGMENT
I did finally remove the redundant input("Client: ") there at the top.
A special thanks #JoachimPileborg for helping, but I have to give it to the little guy just because it was the path I ended up taking.