Tuesday, July 22, 2025

basic client and server socket under (TCP)

what is socket programming?

Socket programming is a way of connecting two nodes on a network to communicate with each other. 

One socket(node) listens on a particular port at an IP, while the other socket reaches out to the other to form a connection. 

The server forms the listener socket while the client reaches out to the server. 

Socket programming is widely used in instant messaging applications, binary streaming, and document collaborations, online streaming platforms, etc. 

 

 

 

  Main Functions Provided by <stdio.h>:

 

Function Purpose
printf() Prints formatted output to the console
scanf() Reads formatted input from the keyboard
getchar() Reads a single character from the keyboard
putchar() Writes a single character to the screen
gets() Reads a string from the keyboard (unsafe)
puts() Writes a string to the screen
fopen() Opens a file
fclose() Closes a file
fread() Reads binary data from a file
fwrite() Writes binary data to a file
fprintf() Prints formatted output to a file
fscanf() Reads formatted input from a file  

 stdlib

The purpose of <stdlib.h> (Standard Library Header) in C is to provide functions for general-purpose operations such as:

  • Memory allocation

  • Program control (exit, abort)

  • Conversions (strings to numbers)

  • Random numbers

  • Sorting and searching

 🧰 Key Functions in <stdlib.h>:

Function Description
malloc() Allocates memory dynamically
calloc() Allocates and zero-initializes memory
realloc() Changes size of previously allocated memory
free() Frees dynamically allocated memory
atoi() Converts string to int
atof() Converts string to float (actually returns double)
atol() Converts string to long int
strtol() Converts string to long with base control
exit() Terminates the program with a return status
abort() Abnormally terminates the program
rand() Generates a random number
srand() Seeds the random number generator
qsort() Sorts an array
bsearch() Performs binary search in a sorted array

 

 🧰 Common Functions in <string.h>:

Function Description
strlen() Returns the length of a string
strcpy() Copies one string to another
strncpy() Copies up to n characters
strcat() Appends one string to another
strncat() Appends up to n characters
strcmp() Compares two strings
strncmp() Compares up to n characters
strchr() Finds first occurrence of a character in a string
strrchr() Finds last occurrence of a character in a string
strstr() Finds first occurrence of a substring
memset() Sets a block of memory to a specific value
memcpy() Copies memory block
memcmp() Compares memory blocks
strtok() Splits a string into tokens (based on delimiter)

 unistd.h

The purpose of <unistd.h> in C is to provide access to the POSIX (Portable Operating System Interface) API, which includes low-level operating system functions for Unix-like systems such as Linux and macOS

 🧰 Key Functions in <unistd.h>:

Function Description
read() Reads data from a file descriptor
write() Writes data to a file descriptor
close() Closes a file descriptor
fork() Creates a new process (child process)
exec() family Replaces current process image with a new process
getpid() Gets the current process ID
getppid() Gets the parent process ID
sleep() Suspends execution for a given number of seconds
usleep() Sleeps for given microseconds
chdir() Changes the current working directory
getcwd() Gets the current working directory
access() Checks if the file exists or has the right permissions
pipe() Creates a pipe for inter-process communication (IPC)
dup(), dup2() Duplicates file descriptors
_exit() Terminates the process immediately (used after fork())

apra/inet.h 

The header file <arpa/inet.h> in C is used for Internet operations, specifically for handling IP addresses and byte-order conversions in network programming on Unix/Linux systems.


🌐 Purpose:

<arpa/inet.h> provides functions to:

  • Convert IP addresses between text and binary formats.

  • Convert data between host byte order and network byte order.

⚠️ It is primarily used in socket programming, especially with IPv4 addresses.

 

 

Function Description
inet_addr() Converts a dotted-decimal IP string to binary (deprecated)
inet_aton() Converts a dotted-decimal IP string to struct in_addr
inet_ntoa() Converts a binary IP address to dotted-decimal string
inet_pton() Converts IP address from text to binary (IPv4 and IPv6)
inet_ntop() Converts IP address from binary to text (IPv4 and IPv6)
htons() Host to network short (16-bit) byte order
htonl() Host to network long (32-bit) byte order
ntohs() Network to host short
ntohl() Network to host long

 

netinet/in.h

The header file <netinet/in.h> in C is used in network (socket) programming, and it defines constants, structures, and functions needed for Internet domain addresses, especially IPv4 and IPv6 protocols.

⚠️ It's specific to Unix/Linux systems, and part of the POSIX sockets API.


🌐 Purpose of <netinet/in.h>:

It provides:

  • Definitions for address families like AF_INET, AF_INET6

  • Structures for IP addresses and port numbers

  • Constants for protocols (TCP, UDP)

  • Useful macros for working with network addresses

    AF_INET     // Address family for IPv4
    AF_INET6    // Address family for IPv6
    IPPROTO_TCP // TCP protocol
    IPPROTO_UDP // UDP protocol
     

 

 sys/socket.h

 

The header file <sys/socket.h> in C is used for socket programming. It defines the core socket API, which allows programs to create, configure, and use sockets to communicate over networks.

✅ It is essential for writing any socket-based application in Unix/Linux systems (e.g., TCP, UDP communication).


🎯 Purpose of <sys/socket.h>

It provides:

  • Functions for creating and managing sockets

  • Definitions for socket types and address families

  • Structures and constants used in socket communication


 

 

Function Description
socket() Creates a new socket
bind() Binds a socket to an IP address and port
listen() Marks a socket as passive (server)
accept() Accepts a connection from a client
connect() Connects a socket to a remote address (client)
send() / recv() Send/receive data through a socket
sendto() / recvfrom() Send/receive data on a socket (for UDP)
setsockopt() Sets socket options
getsockopt() Gets socket options
shutdown() Disables communication on a socket
close() Closes a socket (defined in <unistd.h>)
Constant Meaning
AF_INET Address family for IPv4
AF_INET6 Address family for IPv6
SOCK_STREAM TCP (reliable, connection-oriented)
SOCK_DGRAM UDP (unreliable, connectionless)
SOCK_RAW Raw socket (low-level)

 

server_fd (Server File Descriptor)

  • Meaning: File descriptor for the listening socket.

  • Created by: socket() function.

  • Purpose: This socket listens for incoming client connections.

  • Used in: bind(), listen(), and accept().

 

📌 client_fd (Client File Descriptor)

  • Meaning: File descriptor for the connected client socket.

  • Created by: accept() function.

  • Purpose: This socket is used to communicate with a specific client after the connection is accepted.

  • Used in: read(), write(), send(), recv().

    📦 What is struct sockaddr_in?

    struct sockaddr_in is a structure defined in <netinet/in.h> used specifically for IPv4 addresses.
    It holds all the necessary information about an internet socket endpoint.

    struct sockaddr_in {
        sa_family_t    sin_family;   // Address family (must be AF_INET for IPv4)
        in_port_t      sin_port;     // Port number (must use htons() to convert to network byte order)
        struct in_addr sin_addr;     // IP address (in network byte order)
        char           sin_zero[8];  // Padding (unused)
    };

     

     

    struct sockaddr_in server_addr, client_addr;
     

     


     

📦 Why Do We Need a buffer[] in Socket Code?

Whether you're using TCP or UDP, data is transmitted as raw bytes. The buffer acts like a temporary container for those bytes, either:

  • Coming into your program (received from the network), or

  • Going out to the network (sent to another machine).

    Operation Role of buffer[]
    recv() / read() Store incoming data from the socket
    send() / write() Provide outgoing data to be sent over socket

     

     

    socklen_t addr_len = sizeof(client_addr);

    This line is used in socket programming to specify the size of the client address structure (client_addr) when calling functions like accept(), recvfrom(), or getpeername().

 

 

server_fd = socket(AF_INET, SOCK_STREAM, 0);

This line is creating a socket and assigning its file descriptor to the variable server_fd.

The socket() function returns an integer — a file descriptor that represents the socket.
If it returns -1, the socket creation failed

 

int socket(int domain, int type, int protocol);
 

Argument Value Meaning
domain AF_INET Use IPv4 (Internet Protocol v4)
type SOCK_STREAM Use TCP (connection-oriented, reliable)
protocol 0 Use default protocol for SOCK_STREAM (which is TCP)

 🔧 Socket Types (used as the second argument in socket())

Socket Type Value Description
SOCK_STREAM 1 TCP: Reliable, connection-oriented, stream-based communication (e.g., web browsing).
SOCK_DGRAM 2 UDP: Unreliable, connectionless, datagram-based communication (e.g., video streaming).
SOCK_RAW 3 Low-level raw network protocol access (used in tools like ping or traceroute).
SOCK_SEQPACKET 5 Like SOCK_STREAM, but preserves message boundaries (used with protocols like SCTP).
SOCK_RDM 4 Rare: Reliable datagrams (not commonly supported or used).

 

 

Use Case Recommended Socket Type
HTTP/HTTPS, SSH, FTP SOCK_STREAM (TCP)
DNS, VoIP, Video SOCK_DGRAM (UDP)
Network tools (ping) SOCK_RAW
Message-based file transfer with order SOCK_SEQPACKET (e.g., SCTP)

 

struct sockaddr_in {
    short            sin_family;   // Address family (e.g., AF_INET for IPv4)
    unsigned short   sin_port;     // Port number (in network byte order)
    struct in_addr   sin_addr;     // IP address
    char             sin_zero[8];  // Padding (not used)
};

  • sin_family: Usually set to AF_INET for IPv4.

  • sin_port: Server port (e.g., 8080), converted using htons().

  • sin_addr: IP address (can be set to INADDR_ANY for all local interfaces).

  • sin_zero: Unused, just padding for structure alignment.

     

     


  • 🔗 bind() – What it does

    The bind() system call associates a socket (created using socket()) with a specific IP address and port number.

     int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    struct sockaddr_in server_addr;

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    server_addr.sin_addr.s_addr = INADDR_ANY;
     

     bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); 

     

    Component Description
    server_addr Holds the server’s IP, port, and family info.
    Used in bind(), connect(), accept(), etc.
    Structure type struct sockaddr_in
    Typical use Binding server socket to an IP and port  
    Field Full Meaning Purpose
    sin_family Socket Internet Family Specifies IPv4 (AF_INET)
    sin_port Socket Internet Port Port number (e.g., 8080)
    sin_addr Socket Internet Address Holds the IP address
    sin_addr.s_addr Socket Address Actual 32-bit IP (e.g., 127.0.0.1)

    listen() — What it does:

    The listen() system call puts your server socket into passive mode, meaning:

    "I’m ready to accept incoming connections."

                    int listen(int sockfd, int backlog);
     

     

    Parameter Description
    sockfd The server socket file descriptor (created using socket() and bound using bind())
    backlog The maximum number of pending connections the OS should queue before refusing new ones

    you're now at the heart of TCP server communication: the accept() call. 

     client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addr_len);


    int accept(int server_fd, struct sockaddr *addr, socklen_t *addrlen);

    Parameter Meaning
    server_fd The listening socket (created by socket(), bound by bind(), and ready via listen())
    addr Pointer to a sockaddr structure where the client’s info (IP, port) will be stored
    addrlen Initially set to size of addr and updated with actual size of client address


    🟡 What is returned?

    • accept() returns a new socket file descriptor (client_fd) specific to the connected client.

    • You use this new client_fd to communicate (read/write) with that client.

    • The original server_fd keeps listening for other clients.

    What recv() can handle:

    • Text messages

    • Binary data (files, images, etc.)

    • Structured data (with length headers or delimiters)

       

      recv(client_fd, buffer, buffer_size, 0);
       

      ssize_t recv(int sockfd, void *buf, size_t len, int flags);
       

      Parameter Meaning
      sockfd Socket file descriptor (client_fd) — where you're reading from
      buf Pointer to a buffer where received data will be stored (buffer)
      len Maximum number of bytes to read (buffer_size)
      flags Optional flags (usually 0)
      Returns Number of bytes received, 0 if client closed connection, -1 on error

       

      send() 

      send() may not send all bytes in one go (in rare network cases). Use a loop for large data. 

    send(client_fd, msg, strlen(msg), 0);


     

     memset()

     memset(buffer, 0, BUFFER_SIZE);


    void *memset(void *ptr, int value, size_t num);

    Parameter Meaning
    ptr Pointer to the memory block (buffer)
    value Value to fill with (0 here, means zeroing out)
    num Number of bytes to fill (BUFFER_SIZE)


     

     

     

     

     

     

     

     

     

    No comments:

    Post a Comment

    basic client and server socket under (TCP)

    what is socket programming? Socket programming is a way of connecting two nodes on a network to communicate with each other.  One socket(n...