Search code examples
pythonpython-3.xsocketsheader

what is the use of the header in sockets


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()

Solution

  • 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.