I am using UNIX domain datagram sockets to send records from multiple clients to a single server in a multithreaded program. Everything is done within one process; I'm sending records from multiple threads to a single thread that acts as the server. All threads are assigned to separate cores using their affinity masks.
It works fine with a single client, but now I am using multiple clients. The server will read data from the socket using select() to return file descriptors that are ready ("set"), then use recvfrom to get the records.
But first I need to write the file descriptors to the fd_set struct so I can use it with select(). I created fd_set as a global struct at the top of the C file that contains the programs to open client and server sockets and pass messages between them:
fd_set fdset;
I create client sockets in this way:
int64_t * create_socket_client(struct sockaddr_un claddr, int64_t retvals[])
{
int sfd, j;
size_t msgLen;
ssize_t numBytes;
char resp[BUF_SIZE];
retvals[0] = 0;
retvals[1] = 0;
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1)
return retvals;
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
snprintf(claddr.sun_path, sizeof(claddr.sun_path), "/tmp/ud_ucase_cl.%ld", (long) getpid());
retvals[0] = sfd;
retvals[1] = (int64_t)&claddr;
return retvals;
}
The array retvals is passed in and returned with file descriptor and client address. But to be used with select() I need to insert the file descriptor in the fd_set when the socket is created (in the program above).
Normally that wouldn't be a problem if I knew the layout of fd_set. It's defined in sys/select.h:
/* fd_set for select and pselect. */
typedef struct
{
/* XPG4.2 requires this member name. Otherwise avoid the name
from the global namespace. */
#ifdef __USE_XOPEN
__fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
} fd_set;
but from that definition I can't tell what the fields are or how to get a file descriptor or array of file descriptors into fd_set.
So my question is: how can I get the file descriptors into fd_set so it can be used with select()?
The way to manipulate an fd_set
is with the following macros (from the man
page for select()
):
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
A new fd_set
must be cleared before it is used:
FD_ZERO(&my_fd_set);
To set a file descriptor in an fd_set
, do:
FD_SET(my_fd, &my_fd_set);
Similarly, to remove an fd from an fd_set
, do:
FD_CLR(my_fd, &my_fd_set);
To test if a file descriptor is set in an fd_set
(ie to test which descriptors returned ready):
if (FD_ISSET(my_fd, &my_fd_set)) {
// Take action on my_fd
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.