IPV4 RAW AF INET TCP server client program with Epoll system call ==================================================================== .. tab-set:: .. tab-item:: IPv4 RAW_AF_INET TCP * In this program, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to create a Socket ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to write a data ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to read a data ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use socket APIs ? * `socket `_ * `epoll_create1 `_ * `epoll_ctl `_ * `epoll_wait `_ * `write `_ * `read `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`IPV4 RAW_AF_INET TCP SOCKET FAQs ` * :ref:`Step 1: Sequence Diagram for SERVER.c ` * :ref:`Step 2: Program for Server.c ` * :ref:`Step 3: Compile and Execute Server.c ` * :ref:`Step 4: Sequence Diagram for CLIENT.c ` * :ref:`Step 5: Program for Client.c ` * :ref:`Step 6: Compile and Execute Client.c ` * :ref:`Summary ` .. _epoll_ipv4_raw_af_inet_tcp_socket: .. tab-set:: .. tab-item:: IPV4 RAW_AF_INET TCP SOCKET : FAQs .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Let us answer few basic questions in this socket .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What does ``socket(AF_INET, SOCK_RAW, IPPROTO_TCP)`` do? .. dropdown:: See Answer This call creates a raw socket in the ``AF_INET`` address family for direct access to TCP packets. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow When is it appropriate to use ``SOCK_RAW`` sockets with TCP? .. dropdown:: See Answer It's suitable for tasks like packet capturing, network monitoring, or implementing custom protocols where direct access to TCP packets is needed. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Can this socket be used for regular TCP communication? .. dropdown:: See Answer While technically possible, it's not recommended for regular communication due to increased complexity and potential security risks. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How does a raw TCP socket differ from a regular TCP socket? .. dropdown:: See Answer A raw TCP socket provides direct access to the TCP layer, allowing for manual packet manipulation, whereas regular TCP sockets handle packet details internally. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What are some use cases for raw TCP sockets? .. dropdown:: See Answer Use cases include network sniffing, packet analysis, security auditing, and developing custom network protocols. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How can I capture and analyze TCP packets using raw sockets? .. dropdown:: See Answer You can use the raw socket to capture TCP packets and analyze them using packet analysis tools like Wireshark. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Is error checking needed after creating the socket? .. dropdown:: See Answer Yes, checking for errors ensures that the socket is created successfully before proceeding with further operations. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Why is it important to check the return value of read() and write() in socket programming? .. dropdown:: See Answer It detects issues such as network errors or closed connections. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What is the primary purpose of the epoll system call? .. dropdown:: See Answer To efficiently monitor multiple file descriptors for I/O events .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What types of file descriptors can be monitored using epoll? .. dropdown:: See Answer sockets, files, timerfd, socketpair, message_queue, Namedpipes and shared_memory. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What data structure is used by epoll to store events? .. dropdown:: See Answer Hash table .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How do you handle errors when using the epoll system call? .. dropdown:: See Answer Check the return value for -1 to detect errors, Use perror to print error messages. .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How does epoll handle a set of file descriptors with different states (e.g., reading, writing, exception)? .. dropdown:: See Answer Create the epoll Instance: Before monitoring file descriptors, the application creates an epoll instance using the epoll_create system call. .. code-block:: c int epoll_fd = epoll_create1(0); Register File Discriptors: The application registers file descriptors with the epoll instance using the epoll_ctl system call. It specifies the file descriptor, the events it is interested in (EPOLLIN for readability, EPOLLOUT for writability, etc.), and a user-defined data associated with the file descriptor. .. code-block:: c struct epoll_event event; event.events = EPOLLIN | EPOLLOUT; // Interested in readability and writability event.data.fd = my_file_descriptor; // File descriptor to monitor epoll_ctl(epoll_fd, EPOLL_CTL_ADD, my_file_descriptor, &event); Wait for Events: The application enters a loop where it calls epoll_wait to wait for events. This call blocks until one or more registered file descriptors become ready or until a timeout occurs. .. code-block:: c #define MAX_EVENTS 10 struct epoll_event events[MAX_EVENTS]; int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, timeout_ms); Modify or Remove File Descriptors: The application can dynamically modify or remove file descriptors from the epoll set using the epoll_ctl system call. For example, to modify events for an existing file descriptor: .. code-block:: c struct epoll_event new_event; new_event.events = EPOLLOUT; // Modify to be interested in writability epoll_ctl(epoll_fd, EPOLL_CTL_MOD, my_file_descriptor, &new_event); To remove a file descriptor from the epoll set: .. code-block:: c epoll_ctl(epoll_fd, EPOLL_CTL_DEL, my_file_descriptor, NULL); .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow How does epoll Checking Ready File Descriptors? .. dropdown:: See Answer After epoll_wait returns, the application iterates through the returned events to identify which file descriptors are ready and for what types of events. .. code-block:: c for (int i = 0; i < num_events; ++i) { if (events[i].events & EPOLLIN) { // File descriptor i is ready for reading } if (events[i].events & EPOLLOUT) { // File descriptor i is ready for writing } // Check other events if needed (e.g., EPOLLERR, EPOLLHUP) } .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow What does it mean if epoll returns 0? .. dropdown:: See Answer No file descriptors are ready within the specified timeout. .. _epoll_ipv4_raw_af_inet_tcp_socket_server_sequence_diagram: .. tab-set:: .. tab-item:: Step 1: Sequence Diagram for SERVER.c .. plantuml:: @startuml !theme spacelab start :socket(AF_INET, SOCK_RAW, IPPROTO_TCP); :bind(sock_fd, (struct sockaddr *)servaddr, sizeof(struct sockaddr_in)); :connect(sock_fd, (struct sockaddr*)client_addr, sizeof(struct sockaddr_in)); :epoll_fd = epoll_create1(0); :epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &event); while (while(1)) is (yes) :epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (events[0].data.fd == sock_fd) then (yes) :read(sock_fd, recvbuffer, sizeof(recvbuffer)); :write(sock_fd, buffer, sizeof(buffer)); else (no) endif endwhile (CTRL+c) :(void)close(sock_fd); stop @enduml .. _epoll_ipv4_raw_af_inet_tcp_socket_server_code: .. tab-set:: .. tab-item:: Step 2 : program for server.c * There are many functions used in socket. We can classify those functions based on functionalities. * Create Socket * Bind Socket * Connect Socket * Epoll create1 * Epoll_ctl * Epoll_wait * Write data_packet * Read data_packet * Close socket * ``socket()`` is used to create a new socket. For example, .. code-block:: c sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); * ``bind()`` is used to associate the socket with a specific address and port. For example, .. code-block:: c ret = bind(sock_fd, (struct sockaddr*)servaddr, sizeof(struct sockaddr_in)); * ``connect()`` is used in network programming to establish a connection from a client to a server. For example, .. code-block:: c ret = connect(sock_fd, (struct sockaddr*)client_addr, sizeof(struct sockaddr_in)); * ``epoll_create1()`` creating an epoll instance using epoll_create1, The size parameter is an advisory hint for the kernel regarding the number of file descriptors expected to be monitored, For example, .. code-block:: c epoll_fd = epoll_create1(0); * ``epoll_ctl()`` After creating an epoll instance, file descriptors are added to it using epoll_ctl, For example, .. code-block:: c ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &event); * ``epoll_wait()`` The application then enters a loop where it waits for events using epoll_wait, For example, .. code-block:: c ready_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); * ``read`` system call in C is commonly used to read data from a file descriptor, such as a socket. .. code-block:: c ret = read(sock_fd, recvbuffer, sizeof(recvbuffer)); * ``write`` system call in C is used to write data to a file descriptor, such as a socket. .. code-block:: c ret = write(sock_fd, buffer, sizeof(buffer)); * ``close`` is used to close the socket To free up system resources associated with the socket. For example, .. code-block:: c (void)close(sock_fd); * See the full program below, .. literalinclude:: ipv4_raw_af_inet_tcp/server/server.c :language: c :emphasize-lines: 119, 120, 121, 141, 142, 143, 164, 165, 166, 225, 234, 235, 243, 254, 255, 272, 273, 287 .. _epoll_ipv4_raw_af_inet_tcp_socket_server_side_compile_and_execute: .. tab-set:: .. tab-item:: Step 3: Compile and Execute server.c .. code-block:: c :emphasize-lines: 1, 3 $ gcc -o server server.c $ sudo ./server 127.0.0.1 IP Address: 127.0.0.1 IP Address: 127.0.0.1 checksum is c945 Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server Received : Hello server ^C .. _epoll_ipv4_raw_af_inet_tcp_socket_client_sequence_diagram: .. tab-set:: .. tab-item:: Step 4 : Sequence Diagram for CLIENT.c .. plantuml:: @startuml !theme spacelab start :socket(AF_INET, SOCK_RAW, IPPROTO_TCP); :bind(sockfd, (struct sockaddr*)clientaddr, sizeof(struct sockaddr_in)); :connect(sockfd, (struct sockaddr*)serveraddr, sizeof(struct sockaddr_in)); :epoll_fd = epoll_create1(0); :epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &event); while (while(1)) is (yes) :write(sockfd, buffer, sizeof(buffer)); :epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (events[0].data.fd == sockfd) then (yes) :read(sockfd, recvbuffer, sizeof(recvbuffer)); else (no) endif endwhile (CTRL+c) :(void)close(sockfd); stop @enduml .. _epoll_ipv4_raw_af_inet_tcp_socket_client_code: .. tab-set:: .. tab-item:: Step 5: program for client.c * There are many functions used in socket. We can classify those functions based on functionalities. * Create Socket * Bind Socket * Connect Socket * Epoll create1 * Epoll_ctl * Epoll_wait * Write data_packet * Read data_packet * Close socket * ``socket`` is used to create a new socket. For example, .. code-block:: c sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); * ``bind()`` is used to associate the socket with a specific address and port. For example, .. code-block:: c ret = bind(sockfd, (struct sockaddr*)clientaddr, sizeof(struct sockaddr_in)); * ``connect()`` is used in network programming to establish a connection from a client to a server. For example, .. code-block:: c ret = connect(sockfd, (struct sockaddr*)serveraddr, sizeof(struct sockaddr_in)); * ``epoll_create1()`` creating an epoll instance using epoll_create1, The size parameter is an advisory hint for the kernel regarding the number of file descriptors expected to be monitored, For example, .. code-block:: c epoll_fd = epoll_create1(0); * ``epoll_ctl()`` After creating an epoll instance, file descriptors are added to it using epoll_ctl, For example, .. code-block:: c ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &event); * ``epoll_wait()`` The application then enters a loop where it waits for events using epoll_wait, For example, .. code-block:: c ready_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); * ``write`` system call in C is used to write data to a file descriptor, such as a socket. .. code-block:: c ret = write(sockfd, buffer, sizeof(buffer)); * ``close`` is used to close the socket To free up system resources associated with the socket. For example, .. code-block:: c (void)close(sockfd); * See the full program below, .. literalinclude:: ipv4_raw_af_inet_tcp/client/client.c :language: c :emphasize-lines: 118, 119, 120, 140, 141, 142, 162, 163, 164, 225, 235, 236, 244, 245, 252, 253, 265, 266, 291 .. _epoll_ipv4_raw_af_inet_tcp_socket_client_side_compile_and_execute: .. tab-set:: .. tab-item:: Step 6: Compile and Execute client.c .. code-block:: c :emphasize-lines: 1, 3 $ gcc -o client client.c $ sudo ./client 127.0.0.1 IP Address: 127.0.0.1 IP Address: 127.0.0.1 checksum is c135 Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client Received : Hello client ^C .. tab-set:: .. tab-item:: Enhanced Socket Flexibility with ``AF_INET`` and ``PF_INET`` Domains .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow **Default Domain:** By default, the socket is configured to work in the ``AF_INET`` domain, handling all types of network data. **Additional Domain Support:** We expand the socket's capabilities to also function in the ``PF_INET`` domain, allowing it to operate similarly to ``AF_INET``. **Socket Creation:** We set up a network connection point known as a socket using ``socket(PF_INET, SOCK_RAW, IPPROTO_TCP)``. **Working Scenario:** Despite the change in domain to ``PF_INET``, the socket continues to operate the same way, handling general network data. .. _epoll_ipv4_raw_af_inet_tcp_Summary: .. tab-set:: .. tab-item:: Summary ============== ================================================================================================================== Socket API Learning ============== ================================================================================================================== socket Create a new socket epoll handles a set of file descriptors with different states, such as reading, writing, and exceptions, by using the struct epoll_event structure and the associated event flags.. write used to write data to a file descriptor, such as a socket. read used to read data from a file descriptor, such as a socket. ============== ================================================================================================================== .. card:: See Also * Previous topic * :doc:`../../../sockets/ipv4_raw_af_inet_tcp/poll/poll` * Current topic * :doc:`../../../sockets/ipv4_raw_af_inet_tcp/epoll/epoll` * Next topic * :doc:`../../../sockets/ipv4_raw_af_inet_udp` * Other sockets * :doc:`../../../sockets/ipv6_af_inet6_tcp` * :doc:`../../../sockets/ipv6_af_inet6_udp` * :doc:`../../../sockets/ipv6_raw_af_inet6_icmp` * :doc:`../../../sockets/ipv6_raw_af_inet6_tcp` * :doc:`../../../sockets/ipv6_raw_af_inet6_udp` * :doc:`../../../sockets/ipv6_raw_af_inet6_raw` * :doc:`../../../sockets/raw_af_packet_raw_htons_ETH_P_ALL` * :doc:`../../../sockets/raw_af_packet_tcp_htons_ETH_P_ALL` * :doc:`../../../sockets/raw_af_packet_udp_htons_ETH_P_ALL` * Other IPCs * :doc:`../../../Message_queues/Message_queues` * :doc:`../../../NamedPipes/NamedPipes` * :doc:`../../../Netlink/Netlink` * :doc:`../../../Shared_Memory/Shared_Memory` * :doc:`../../../Shared_Memory_2_FDS/Shared_Memory_2_FDS` * :doc:`../../../SocketPair/SocketPair` * :doc:`../../../Timerfd/Timerfd`