i am new to coding , i am learning sockets right now so i watched this video on youtube here and the other 3 videos of the tutorial but still i didn't understand clearly the use of the header why can't we just send it in byte format like what is his role . i made some improvment with the code with threads, here is it (sorry of my english)
///server side///
import socket
import select
import time
HEADER = 10
IP = socket.gethostbyname(socket.gethostname())
PORT= 1234
server_socket = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET , socket.SO_REUSEADDR , 1)
server_socket.bind((IP , PORT))
server_socket.listen()
print("sioud-server is on ")
socket_list = [server_socket]
clients = {}
def message_recv(client_socket):
try:
message_header = client_socket.recv(HEADER)
if not len(message_header) :
return False
message_length = int(message_header.decode("utf-8").strip())
return {"header" : message_header , "data" : client_socket.recv(message_length) }
except:
return False
while True :
read_socket , _ , exception_socket = select.select(socket_list , [] , socket_list )
for notified_socket in read_socket :
if notified_socket == server_socket:
client_socket , client_address = server_socket.accept()
user = message_recv(client_socket)
if user is False :
continue
socket_list.append(client_socket)
clients[client_socket] = user
print(f"accepted new connection from {client_address[0]} : {client_address[1]} username : {user['data'].decode('utf-8')}")
else :
message = message_recv(notified_socket)
if message is False :
print(f"closed connection from {clients[notified_socket]['data'].decode('utf-8')}")
socket_list.remove(notified_socket)
del clients[notified_socket]
continue
user = clients[notified_socket]
print(f"received message from {user['data'].decode('utf-8')}: {message['data'].decode('utf-8')}")
for client_socket in clients:
if client_socket != notified_socket :
client_socket.send(user['header'] + user['data'] + message['header'] + message['data'])
for notified_socket in exception_socket :
socket_list.remove(notified_socket)
del clients[notified_socket]
client-side
import socket
import select
import errno
import sys
import time
import threading
HEADER = 10
IP = "your ip adrss"
PORT= 1234
my_username = input("Username: ")
time.sleep(1)
print("welcome in sioud-server")
print("note : click 'enter' to see the other users msgs or just send a msg")
client_socket = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
client_socket.connect((IP , PORT))
username = my_username.encode("utf-8")
username_header = f"{len(username):<{HEADER}}".encode("utf-8")
client_socket.send(username_header + username)
pol = True
running = True
def recieve_thread():
while running :
username_header = client_socket.recv(HEADER)
if not len(username_header):
print('Connection closed by the server')
sys.exit()
username_length = int(username_header.decode('utf-8').strip())
username = client_socket.recv(username_length).decode('utf-8')
message_header = client_socket.recv(HEADER)
message_length = int(message_header.decode('utf-8').strip())
message = client_socket.recv(message_length).decode('utf-8')
time.sleep(1)
print(f'{username}: {message}')
def send_msg():
while pol:
message = input(f"/")
if message :
message = message.encode("utf-8")
message_header = f"{len(message):<{HEADER}}".encode("utf-8")
client_socket.send(message_header + message)
thread = threading.Thread(target =recieve_thread)
thread.start()
thread_ = threading.Thread(target =send_msg)
thread_.start()
TCP is a byte stream. Unlike UDP, TCP has no concept of messages, that is an application-level concept. A TCP sender needs a way to indicate where one message ends and the next begins, so the TCP receiver can receive each message correctly. There are only 2 way to do that in TCP:
send a message's length before sending the message's data.
send a unique terminator after each message, that is guaranteed never to appear inside any message.
In this example, the code is using the former approach. The sender is sending a message's data length as an integer in 10-byte string format, followed by the actual data bytes. The receiver is first reading the 10-byte string and parsing it into an integer, and then reading the specified number of bytes that follow.