I'm developing an app and I want to send msgs from the client socket (TCP) to the server socket. I want to send 3 messages, send one, wait till the ACK from the server, send another msg wait till the ACK from the server...
This is my code (client side):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((host,port))
sock.sendall(bytes(INIT_MSG, "UTF-8"))
sock.sendall(bytes(FREQ_MSG, "UTF-8"))
sock.sendall(bytes(KEY_MSG, "UTF-8"))
And in server side:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("",PORT))
s.listen()
counter = 0
conn, addr = s.accept()
print("Connected by:", addr)
while True:
data = conn.recv(1024)
if not data:
break
But when I use Wireshark to look at the frames, all the data is send in one frame instead of 3. I believe the main problem is in the server side which accepts 1024b.
How can I fix it?
Related
I have a problem with the actual handling of a client/ server System.
For a project I have a control unit, to which sensor data is sent.
After that, I want the Control Unit to send the data to a server, where the data is captured.
So now I have a client (HoloLens2), which connects to the server over a TCP-connection and requests data.
The Problem now, is that i don't know exactly how I should handle those different requests.
I've already coded the following lines for the server.
With this I am able to successfully open the TCP-Connection:
import socket
import threading
HEADER = 64 # Length of HEADER-message
HOST = socket.gethostbyname(socket.gethostname())
PORT = 28500 # Port to listen on (non-privileged ports are > 1023)
ADDR = (HOST, PORT)
FORMAT = 'utf-8'
DISCIONNECT_MESSAGE = "!DISCONNECT"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(ADDR)
#Setup for listening. This function runs for each client
def handle_client(connection, cl_addr):
print(f"[NEW CONNECTION] {cl_addr} connected.")
connected = True
while connected:
#Wait on this line until we receive a message with 64 bytes
msg_length = connection.recv(HEADER).decode(FORMAT)
#Read out the information about the followed message in the HEADER-Message
msg_length = int(msg_length)
#Receive the actual message
msg = connection.recv(msg_length).decode(FORMAT)
if(msg == DISCIONNECT_MESSAGE):
connected = False
print(f"[{cl_addr}] {msg}")
connection.close()
#start socket server
def start():
server.listen()
print(f"[LISTENING] Server is listening on {HOST}")
while True:
#Wait on this line until new connection established
conn, addr = server.accept()
#when connection successfull, start new thread
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1} ")
print("[STARTING] server is starting . . .")
start()
If I now want to send different data for different requests, for example when the message is "!SENSOR1",
I want to send all the data captured of the sensor.
Do I have to implement the whole thing simply with if-else query like this:
if(msg == "!SENSOR1"):
connection.send("This is the data from sensor 1: ")
Or is there a much more efficient way to handle this problem?
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.
I'm trying to learn about sockets and how to create a server and a client in python.
While reading this great article from Real Python I had difficulties understanding why the server receives two strings, when I only send one.
server.py
import socket
HOST = "127.0.0.1"
PORT = 65432
server = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
with server:
server.bind((HOST, PORT))
server.listen()
print("Waiting for connections...")
conn, addr = server.accept()
print("Accepted!")
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
print(f"Message received: {data}")
if not data:
print(f"Breaking while loop and closing connection")
break
conn.sendall(data)
client.py
import socket
HOST = "127.0.0.1"
PORT = 65432
client = socket.socket(
family=socket.AF_INET,
type=socket.SOCK_STREAM
)
with client as c:
c.connect((HOST, PORT))
# Get input from client
message = input("Enter your message: ")
c.sendall(str.encode(message))
data = c.recv(1024)
print(f"Received {data}")
Output from server.py after running the server and client:
Waiting for connections...
Accepted!
Connected by ('127.0.0.1', 64476)
Message received: b'message'
Message received: b''
Breaking while loop and close connection
Why does the server receive two messages (b'message' and b'')
The recv() can only empty string when the other end is gone. You are unable to send zero length data over socket (try it :). So the fact you are seeing this is simply because you are not checking for that.
PS: your client's last print() is not correctly indented.
I have the code below. Right now I am just putting the sequence number and ACK in the payload. I would like to know two things:
How can I put this info into the header for both client and server?
How can I print out the ACK on the client and Sequence number on server?
I am using Python 2.7.13 on Linux.
Client:
import socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.settimeout(4.0)
message = "Sequence Number: 100\nACK: 1"
addr = ("127.0.0.1", 6000)
client_socket.sendto(message, addr)
try:
data, server = client_socket.recvfrom(1024)
# Print the ACK the server sent
except socket.timeout:
print('Timed out')
Server:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(("127.0.0.1", 6000))
while True:
message, address = server_socket.recvfrom(1024)
# Print the sequence number the client sent
# Set ACK to 0 and send this ACK to the client
server_socket.sendto(message, address)
I am writing a TCP server in Python.
I want the server to close the connection right after the server send the SYN-ACK (response to SYN from client) without waiting to the client's ACK response (without finishing the handshake).
That's my server:
def get_tcp(port, data_len=1024):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', port))
sock.listen(1)
conn, addr = sock.accept()
conn.close()
Is there a way to do it?
Thank you very much