Hey guys! Let's dive into creating a simple daytime client-server program using C. This is a fantastic way to understand basic network programming concepts. I'll walk you through the server side, the client side, and how they communicate. So, buckle up, and let's get started!
Understanding the Daytime Protocol
Before we jump into the code, let's understand the daytime protocol. It's a very simple protocol where a server listens on a specific port (usually port 13), and when a client connects, the server sends back a human-readable date and time string. That's it! No complex handshakes or data formats. This simplicity makes it an excellent starting point for learning network programming.
The Role of the Server
The server's job is to listen for incoming connections, accept them, get the current date and time, format it into a string, send it to the client, and then close the connection. The key here is handling multiple clients potentially connecting at the same time. In a basic example, we'll handle one client at a time to keep things simple, but in a more robust application, you'd want to use threads or asynchronous I/O to handle multiple clients concurrently.
The Role of the Client
The client's role is even simpler: connect to the server, read the date and time string sent by the server, display it to the user, and then close the connection. The client needs to know the server's IP address and the port number the server is listening on. The client initiates the connection, making it a straightforward process.
Setting Up the Server
Alright, let's start with the server code. We'll use standard C libraries like stdio.h, stdlib.h, string.h, and unistd.h for basic input/output, memory allocation, string manipulation, and POSIX operating system API, respectively. We'll also need sys/socket.h and netinet/in.h for socket programming.
Essential Includes
First, we'll include all necessary header files:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
These includes provide all the functions and data structures we need for socket creation, address handling, and basic I/O.
Creating the Socket
Next, we need to create a socket. A socket is an endpoint for network communication. We'll use the socket() function, specifying AF_INET for IPv4 addresses, SOCK_STREAM for TCP (a reliable, connection-oriented protocol), and 0 for the default protocol.
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
If socket() returns -1, it means there was an error creating the socket, and we exit the program.
Binding the Socket
Now, we need to bind the socket to a specific address and port. This tells the operating system that our server will be listening for incoming connections on that address and port. We'll use the sockaddr_in structure to specify the address and port.
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY; // Listen on all available interfaces
address.sin_port = htons(13); // Daytime port
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
INADDR_ANY allows the server to listen on all available network interfaces. htons() converts the port number from host byte order to network byte order. If bind() returns a negative value, it indicates an error.
Listening for Connections
After binding the socket, we need to start listening for incoming connections using the listen() function. This function tells the operating system to start accepting connections on the socket.
if (listen(server_fd, 3) < 0) { // Listen with a backlog of 3
perror("listen failed");
exit(EXIT_FAILURE);
}
The second argument to listen() is the backlog, which specifies the maximum number of pending connections that can be queued up before the server starts refusing new connections.
Accepting Connections and Sending the Daytime
Now, we enter the main loop where we accept incoming connections, get the current date and time, and send it to the client.
int addrlen = sizeof(address);
int new_socket;
while(1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
time_t now = time(NULL);
char *ctime_str = ctime(&now);
send(new_socket, ctime_str, strlen(ctime_str), 0);
close(new_socket);
}
accept() blocks until a client connects. It returns a new socket file descriptor for the accepted connection. We then get the current time using time(), convert it to a string using ctime(), send the string to the client using send(), and close the connection using close(). The while(1) loop ensures that the server continues to accept new connections.
Crafting the Client
Now, let's move on to the client side. The client needs to connect to the server, read the daytime string, and display it.
Essential Includes
Just like the server, we'll start by including the necessary header files:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
arpa/inet.h is needed for functions like inet_pton() which converts IP addresses from text to binary form.
Creating the Socket
We create a socket in the same way as the server:
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
Connecting to the Server
To connect to the server, we need to specify the server's IP address and port number. We'll use the sockaddr_in structure again.
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(13);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
printf("Invalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("connect failed");
exit(EXIT_FAILURE);
}
Here, we're connecting to the server running on the same machine (127.0.0.1, also known as localhost) on port 13. inet_pton() converts the IP address from text form to binary form. connect() establishes a connection to the server.
Receiving and Displaying the Daytime
Once connected, we receive the daytime string from the server and display it.
char buffer[1024] = {0};
read(sock, buffer, 1024);
printf("Daytime: %s\n", buffer);
close(sock);
We read up to 1024 bytes from the socket into the buffer, print the contents of the buffer, and then close the socket.
Putting It All Together
Server Code (daytime_server.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
int port = 13;
// 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);
// Forcefully attaching socket to the port 13
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen failed");
exit(EXIT_FAILURE);
}
while(1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
time_t now = time(NULL);
char *ctime_str = ctime(&now);
send(new_socket, ctime_str, strlen(ctime_str), 0);
close(new_socket);
}
return 0;
}
Client Code (daytime_client.c)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int sock = 0, valread;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(13);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0) {
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
printf("\nConnection Failed \n");
return -1;
}
valread = read(sock, buffer, 1024);
printf("%s\n",buffer );
return 0;
}
Compiling and Running
To compile the server, use the command:
gcc daytime_server.c -o daytime_server
To compile the client, use the command:
gcc daytime_client.c -o daytime_client
Run the server in one terminal:
./daytime_server
And run the client in another terminal:
./daytime_client
The client should display the current date and time received from the server.
Error Handling and Improvements
Robust Error Handling
The provided code includes basic error handling using perror() and exit(). However, in a production environment, you'd want to implement more robust error handling, such as logging errors to a file or implementing retry mechanisms.
Concurrent Server
The server implementation provided here handles only one client at a time. To handle multiple clients concurrently, you can use threads or asynchronous I/O. Using threads involves creating a new thread for each incoming connection, allowing the server to handle multiple clients simultaneously. Asynchronous I/O, on the other hand, allows the server to handle multiple connections without blocking.
Security Considerations
For a real-world application, security is paramount. The daytime protocol itself isn't secure, as it doesn't involve any authentication or encryption. If you're building a more complex application, consider using TLS/SSL to encrypt the communication between the client and server.
Conclusion
And there you have it! You've created a simple daytime client-server program in C. This is a great stepping stone to understanding more complex network programming concepts. Remember to play around with the code, experiment with different features, and always strive to improve your error handling and security. Happy coding, guys! Keep exploring and building!
Lastest News
-
-
Related News
NYC On A Budget: Best Cheap Eats In New York
Alex Braham - Nov 12, 2025 44 Views -
Related News
Nepal Vs Oman Live: Your Guide To Watching The Match
Alex Braham - Nov 9, 2025 52 Views -
Related News
Shelbyville Casino: Seafood Buffet Delights!
Alex Braham - Nov 13, 2025 44 Views -
Related News
Seattle Storm Roster: Meet The Players
Alex Braham - Nov 13, 2025 38 Views -
Related News
Best Shooting Ranges In Bangkok
Alex Braham - Nov 13, 2025 31 Views