Socket errors are a very common occurrence in network communication and this can rise at many stages of the process including connection establishment, data transmission, and disconnection. These errors can be caused by a wide range of factors such as network failures, connection timeouts, resource limitations, or incorrect configuration settings.
Let us discuss about the two different approaches on how to catch the socket errors in the C programming language using the “perror()” and “strerror()” functions.
What Are Socket Errors?
The socket errors in C language are mainly identified by negative return value or specific error codes that are returned by socket functions. These error codes provide valuable information about the nature of the error and help us to detect as well as to solve the issues. If the socket function returns a negative value, it means that some error came at the time of execution. For example, if the “socket()” function fails to create a socket, it may return a negative value to indicate the failure. We can easily detect and respond to such errors by checking this.
In addition to negative return values, socket functions also set the “errno” variable which is a global variable that stores the specific error code that is associated with the most recent system or library function call. The “errno” variable can be accessed using the “<errno.h>” header file and contains predefined error codes that shares extra information about the reason of the error. By understanding the significance of return values and error codes, we can identify the source of the error and take appropriate action.
Programming Example 1: Catch the Socket Errors Using the Strerror()
Function
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main ()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
// Create a socket
socketDescriptor = socket (AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0)
{
perror ("Socket creation failed");
exit(EXIT_FAILURE);
}
// Set up the server address
serverAddress.sin_family = AF_INET;
// Let us use an example port number
serverAddress.sin_port = htons (7070);
// Local IP address
serverAddress.sin_addr.s_addr = inet_addr ("127.0.0.1");
// Connect to the server
if (connect (socketDescriptor, (struct sockaddr * ) & serverAddress, sizeof (serverAddress)) < 0)
{
perror ("Connection failed");
exit (EXIT_FAILURE);
}
// Send and receive data
// Let us Close the socket
close (socketDescriptor);
return 0;
}
Output:
$ ./err
Connection failed: Connection refused
Explanation:
In this programming example, we use the socket() function to create a socket. If the returned socket descriptor is less than 0, which indicates an error during the socket creation, it uses the “perror()” function to display the corresponding error message and it exits the program. To establish a connection, it sets up the server address and attempts to connect using the connect() function to check if the return value is less than 0. In case of a connection failure, the “perror()” function is used again to display an error message and the program will exit. With this approach, we can easily catch the socket errors in C language. This allows us to show the informative error messages and to properly terminate the program.
Programming Example 2: Catch the Socket Errors Using the Perror() Function
#include <stdlib.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <unistd.h>
int main ()
{
int socketDescriptor;
struct sockaddr_in serverAddress;
// Create a socket
socketDescriptor = socket (AF_INET, SOCK_STREAM, 0);
if (socketDescriptor < 0)
{
fprintf (stderr, "Failed to create socket: %s \n", strerror (errno));
exit (EXIT_FAILURE);
}
// Set up the server address
serverAddress.sin_family = AF_INET;
// Let us use an example port number
serverAddress.sin_port = htons (7070);
// Local IP address
serverAddress.sin_addr.s_addr = inet_addr ("127.0.0.1");
// now we attempt for server connection
if (connect (socketDescriptor, (struct sockaddr *) & serverAddress, sizeof (serverAddress)) < 0) {
fprintf (stderr, "Failed to connect: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
// Send and receive data
// Close the socket
if (close (socketDescriptor) < 0)
{
fprintf (stderr, "Socket closure failed: %s\n", strerror (errno));
exit (EXIT_FAILURE);
}
printf ("Socket closed successfully.\n");
return 0;
}
Output:
$ ./error
Failed to connect: Connection refused
Explanation:
In this programming example, we catch the socket errors in C using the “strerror()” function. This function allows us to convert the error code that is stored in the “errno” variable into a human-readable error message. By including the “<string.h>” header file, we can access the “strerror()” function and provide it with the “errno” value to obtain the corresponding error message. Here in this program, after creating a socket, we check if the socket descriptor is less than 0 which means a failure. If an error occurs, we use the “strerror()” function along with the “errno” value to retrieve an error message. The “fprintf()” function displays the error message on the standard error stream. Finally, the program exits with a failure status.
Conclusion
By understanding the return values and error codes that are provided by socket functions, we can easily catch and handle these socket errors in C. In the first programming example, we explained how to catch the error and return values using the “perror()” function. In the second example, we explained the “strerror()” function to obtain the detailed error messages. By understanding these methods, we can display the informative error messages and properly terminate our programs in the socket programming.