I am trying to make a server.c file that supports 3 sockets, which are represented by 3 respective client classes: client1, client2, client3.
In my server.c file, I currently have this code which I found on the internet.
If I wanted to make it have 3 sockets. I want to use the select() command to see the write activities of the 3 clients. My question is how can I use this to support 3 sockets.
Can I bind the 3 clients to 3 sockets that the server can listen to? If so, how can the server listen to these 3 sockets respectively? With an array possibly?
#include <stdio.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#define socket1 "sock1"
#define socket2 "sock2"
#define socket3 "sock3"
int main(int argc, char *argv[]) {
//struct sockaddr_un addr;
struct sockaddr_un addr1;
struct sockaddr_un addr2;
struct sockaddr_un addr3;
char buf[100];
int socket1;
int socket2;
int socket3;
//int fd;
int cl,rc;
if (argc > 1) socket_path=argv[1];
if ( (socket1 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr1, 0, sizeof(addr1));
addr1.sun_family = AF_UNIX;
strncpy(addr1.sun_path, socket_path, sizeof(addr1.sun_path)-1);
unlink(socket_path1);
if ( (socket2 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr2, 0, sizeof(addr2));
addr1.sun_family = AF_UNIX;
strncpy(addr2.sun_path, socket_path, sizeof(addr2.sun_path)-1);
unlink(socket_path2);
if ( (socket3 = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("socket error");
exit(-1);
}
memset(&addr3, 0, sizeof(addr3));
addr3.sun_family = AF_UNIX;
strncpy(addr3.sun_path, socket_path, sizeof(addr3.sun_path)-1);
unlink(socket_path3);
if (bind(socket1, (struct sockaddr*)&addr1, sizeof(addr1)) == -1) {
perror("bind error");
exit(-1);
}
if (bind(socket2, (struct sockaddr*)&addr2, sizeof(addr2)) == -1) {
perror("bind error");
exit(-1);
}
if (bind(socket3, (struct sockaddr*)&addr3, sizeof(addr3)) == -1) {
perror("bind error");
exit(-1);
}
if (listen(socket1, 5) == -1) {
perror("listen error");
exit(-1);
}
if (listen(socket2, 5) == -1) {
perror("listen error");
exit(-1);
}
if (listen(socket3, 5) == -1) {
perror("listen error");
exit(-1);
}
while (1) {
if ( (cl = accept(fd, NULL, NULL)) == -1) {
perror("accept error");
continue;
}
while ( (rc=read(cl,buf,sizeof(buf))) > 0) {
printf("read %u bytes: %.*s\n", rc, rc, buf);
}
if (rc == -1) {
perror("read");
exit(-1);
}
else if (rc == 0) {
printf("EOF\n");
close(cl);
}
}
return 0;
}
If you want three listening sockets in the same process, you have to make them unique. In the AF_INET
family you do that by bind(2)
-ing different ports, in the AF_UNIX
family you do that with different paths.
Also your line:
char *socket_path = "\0hidden";
has at least two problems:
const char[8]
, which decays to const char*
pointer type, but not char*
type. Make the left hand side const char*
. Plus, compile with higher warning level, like -Wall -pedantic
to get help from your compiler.strncpy(3)
not copy anything, since it copies at most n characters from the string pointed to by src, including the terminating null byte ('\0')
.Create a function that take UNIX path as an argument and creates, binds, and marks socket as listening, and returns created socket descriptor. Call it three times - you have three listening UNIX sockets. Setup select(2)
on them for reading - that'll tell you when client connections arrive. At that point call accept(2)
on the active socket to get connected client socket, which is separate from the listening socket itself.