To get a basic understanding of an abstract Namespace socket connection, refer the article provided here. To create a socket connection path which does not have an entry in the filesystem, the below method is used
const char *path= “#unix_socket.sock”;
The ‘#‘ in the above name will be replaced with ‘\0‘ (Null byte) when it needs to bind to a path. This is in contrast to the path that was created in the basic AF_UNIX connection as shown below.
const char *path= “/tmp/unix_socket.sock”;
When a “\0” is used in the path, the operating system understands the path to be an abstract path and creates a path accordingly. Let us look at an abstract namespace socket code and analyze the code for the same.
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
const char *path= “#unix_socket.sock”;
struct sockaddr_un *servaddr = NULL, *cliaddr = NULL;
int sockserver, sockclient;
/* Interrupt_handler so that CTRL +C can be used
* to exit the program */
void interrupt_handler (int signum) {
close(sockserver);
close(sockclient);
free(servaddr);
free(cliaddr);
printf(“socket connection closed\n”);
exit(0);
}
int main () {
int length;
char buffer[50];
char *string = “Hello from server”;
/* signal handler to exit out of while 1 loop */
signal (SIGINT, interrupt_handler);
signal (SIGPIPE, interrupt_handler);
/* Part 1 – create the socket */
sockserver = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockserver < 0) {
printf(“creating server socket failed\n”);
exit(0);
}
/* Part 2 – fill the structure and bind to the socket path
*/
servaddr = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
if (servaddr == NULL) {
printf(“unable to allocate memory\n”);
goto end;
}
servaddr->sun_family = AF_UNIX;
if ((strlen(path)) > sizeof(servaddr->sun_path)) {
printf(“Path is too long\n”);
goto end;
}
snprintf(servaddr->sun_path, (strlen(path)+1), “%s”, path);
servaddr->sun_path[0] = ‘\0’;
if (0 != (bind(sockserver,(struct sockaddr *)servaddr, sizeof(struct sockaddr_un)))) {
printf(“Unable to bind to the socket path\n”);
goto end1;
}
/* Part 3 – make the server socket a passive socket and accept connections
* from client stations */
if(-1 == listen(sockserver, 1)) {
printf(“Listen Failed\n”);
return -1;
}
cliaddr = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
if (cliaddr == NULL) {
printf(“Unable to allocate memory\n”);
goto end2;
}
printf(“waiting for connection\n”);
sockclient = accept(sockserver, (struct sockaddr *)cliaddr, &length);
if (sockclient < 0) {
printf(“unable to accept client connection\n”);
goto end2;
}
/* read and write data from/to socket */
while (1) {
memset(buffer, 0, sizeof(buffer));
read(sockclient, buffer, sizeof(buffer));
printf(“%s\n”, buffer);
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, (strlen(string)+1), “%s”, string);
write(sockclient, buffer, sizeof(buffer));
}
end3:
if(sockclient >= 0)
close(sockclient);
end2:
free(cliaddr);
end1:
free(servaddr);
end:
close(sockserver);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
const char *path= “#unix_socket.sock”;
struct sockaddr_un *servaddr = NULL;
int sockserver;
/* Interrupt_handler so that CTRL +C can be used
* to exit the program */
void interrupt_handler (int signum) {
close(sockserver);
free(servaddr);
printf(“socket connection closed\n”);
exit(0);
}
int main () {
int length;
char buffer[50];
char *string = “Hello from client”;
/* signal handler to exit out of while 1 loop */
signal (SIGINT, interrupt_handler);
signal (SIGINT, interrupt_handler);
/* Part 1 – create the socket */
sockserver = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockserver < 0) {
printf(“creating client socket failed\n”);
exit(0);
}
/* Part 2 – fill the structure and bind to the socket path */
servaddr = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
servaddr->sun_family = AF_UNIX;
if ((strlen(path)) > sizeof(servaddr->sun_path)) {
printf(“Path is too long\n”);
goto end1;
}
snprintf(servaddr->sun_path, (strlen(path)+1), “%s”, path);
servaddr->sun_path[0] = ‘\0’;
if (0 != (connect(sockserver, (struct sockaddr *)servaddr, sizeof(struct sockaddr_un)))) {
printf(“unable to connect to the server\n”);
goto end1;
}
/* read and write data from/to socket */
while (1) {
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, (strlen(string)+1), “%s”, string);
write(sockserver, buffer, sizeof(buffer));
memset(buffer, 0, sizeof(buffer));
read(sockserver, buffer, sizeof(buffer));
printf(“%s\n”, buffer);
}
end1:
free(servaddr);
close(sockserver);
return 0;
}
Pingback: Abstract Namespace Socket Connections | Hitch Hiker's Guide to Learning
Pingback: Anayzing the Abstract Namespace stream socket code | Hitch Hiker's Guide to Learning