Daytime Client Server Program In C: A Simple Guide

by Alex Braham 51 views

Hey guys! Ever wondered how computers talk to each other to get the current time? That's where the Daytime Client Server Program comes in handy. Today, we're diving into building a simple daytime client-server program using C. This is an excellent way to understand basic network programming concepts. So, buckle up, and let’s get started!

Understanding the Basics

Before we jump into the code, let's break down what we're trying to achieve. A client-server model involves two main components:

  • Server: The server listens for incoming connections on a specific port. When a client connects, the server processes the request (in our case, providing the current date and time) and sends back a response.
  • Client: The client initiates a connection to the server. Once connected, it waits for the server's response, which it then displays to the user.

The daytime service is a very simple service that returns the current date and time. It's a classic example for demonstrating network programming because it's straightforward and easy to understand. We'll be using sockets, which are the fundamental building blocks for network communication in C.

To put it simply, think of the server as a clock tower and the clients as people who want to know the time. The people (clients) ask the clock tower (server) for the time, and the clock tower responds with the current time. Now, let's see how this works in C code!

Setting Up the Server

First, let's create the server-side code. The server needs to:

  1. Create a socket.
  2. Bind the socket to a specific address and port.
  3. Listen for incoming connections.
  4. Accept a connection.
  5. Send the current date and time to the client.
  6. Close the connection.

Here’s a basic example:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 13  // Daytime port

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    char buffer[1024] = {0};
    time_t now;

    // Creating socket file descriptor
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    // Binding the socket to the specified address and port
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // Listening for incoming connections
    if (listen(server_fd, 3) < 0) {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }

    printf("Server listening on port %d\n", PORT);

    // Accepting a connection
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
        perror("accept failed");
        exit(EXIT_FAILURE);
    }

    // Getting the current time
    now = time(NULL);
    snprintf(buffer, sizeof(buffer), "%s", ctime(&now));

    // Sending the time to the client
    send(new_socket, buffer, strlen(buffer), 0);
    printf("Time sent to client: %s", buffer);

    // Closing the connection
    close(new_socket);
    close(server_fd);

    return 0;
}

In this code:

  • We include necessary header files for socket programming and time manipulation.
  • We define the port number (PORT) to be 13, which is the standard daytime port.
  • We create a socket using socket(). The AF_INET argument specifies the IPv4 address family, and SOCK_STREAM indicates that we're using TCP.
  • We bind the socket to an address and port using bind(). INADDR_ANY allows the server to listen on all available network interfaces.
  • We listen for incoming connections using listen(). The argument 3 specifies the maximum number of queued connections.
  • We accept a connection using accept(). This creates a new socket for the connection.
  • We get the current time using time() and format it into a string using ctime().
  • We send the time to the client using send().
  • Finally, we close the sockets using close().

Compile this code using a C compiler (like GCC):

gcc daytime_server.c -o daytime_server

Then, run the server:

./daytime_server

You should see the message "Server listening on port 13" if everything goes well. Now, let's create the client.

Building the Client

The client needs to:

  1. Create a socket.
  2. Connect to the server.
  3. Receive the data (date and time) from the server.
  4. Display the received data.
  5. Close the connection.

Here’s the client-side code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 13
#define SERVER_IP "127.0.0.1" // Loopback address for testing

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;
    char buffer[1024] = {0};

    // Creating socket file descriptor
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        printf("Socket creation error \n");
        return -1;
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);

    // Convert IPv4 and IPv6 addresses from text to binary form
    if (inet_pton(AF_INET, SERVER_IP, &serv_addr.sin_addr) <= 0) {
        printf("Invalid address / Address not supported \n");
        return -1;
    }

    // Connecting to the server
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        printf("Connection Failed \n");
        return -1;
    }

    // Receiving data from the server
    read(sock, buffer, sizeof(buffer) - 1);

    printf("Current time from server: %s\n", buffer);

    // Closing the connection
    close(sock);

    return 0;
}

In this code:

  • We include the necessary header files for socket programming.
  • We define the port number (PORT) and the server IP address (SERVER_IP). For testing on the same machine, we use the loopback address 127.0.0.1.
  • We create a socket using socket().
  • We set the server address and port in the serv_addr structure.
  • We convert the IP address from text to binary form using inet_pton().
  • We connect to the server using connect().
  • We read the data sent by the server using read().
  • We print the received data to the console.
  • Finally, we close the socket using close().

Compile this code using GCC:

gcc daytime_client.c -o daytime_client

Before running the client, make sure the server is running. Then, execute the client:

./daytime_client

You should see the current date and time printed to the console, received from the server!

Error Handling and Improvements

While the above code provides a basic implementation, it's essential to add error handling to make it more robust. Here are a few things you can improve:

  • Check return values: Always check the return values of functions like socket(), bind(), listen(), accept(), connect(), send(), and read() for errors. Use perror() to print descriptive error messages.
  • Handle interrupted system calls: System calls like accept() and read() can be interrupted by signals. You can use the errno variable and the EINTR error code to handle these interruptions and retry the call.
  • Add timeouts: To prevent the client from blocking indefinitely while waiting for data from the server, you can set a timeout on the socket using the setsockopt() function.
  • Use non-blocking sockets: For more advanced scenarios, you can use non-blocking sockets and the select() or poll() functions to handle multiple connections simultaneously.
  • Secure your communication: For real-world applications, consider using encryption protocols like TLS/SSL to secure the communication between the client and the server.

Conclusion

And there you have it! You've successfully built a simple daytime client-server program in C. This example provides a foundation for understanding network programming concepts. Feel free to experiment with the code, add more features, and explore other network services. Happy coding!

Remember, the world of network programming is vast and exciting. This is just the beginning. Keep exploring, keep learning, and keep building awesome things!

Keywords: Daytime Client Server Program, C programming, Socket Programming, Network Communication, Client-Server Model