Hi,
Until recently I have been using select() to wait for activity on file descriptors, however this seems less efficient than poll. I rewrote the program using poll:
Server:
Code:
#include <stdio.h>#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <poll.h>
#define POLL_SIZE 32
#define LISTEN_QUEUE 5
#define SOCKET_PATH "web/server_socket.sock"
int main()
{
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_un server_address;
struct sockaddr_un client_address;
int result;
struct pollfd poll_set[POLL_SIZE];
int numfds = 0;
int max_fd = 0;
unlink(SOCKET_PATH);
server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
server_address.sun_family = AF_UNIX;
strcpy(server_address.sun_path, SOCKET_PATH);
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *)&server_address, (socklen_t)server_len);
listen(server_sockfd, 5);
poll_set[0].fd = server_sockfd;
poll_set[0].events = POLLIN;
numfds++;
//signal(SIGPIPE, SIG_IGN);
update_maxfd(server_sockfd, &max_fd);
while (1) {
char ch;
int fd_index;
int nread;
printf("Waiting for client (%d total)...\n", numfds);
//result = select( (max_fd + 1), &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *) 0);
poll(poll_set, numfds, 10000);
for(fd_index = 0; fd_index < numfds; fd_index++)
{
if( poll_set[fd_index].revents & POLLIN ) {
if(poll_set[fd_index].fd == server_sockfd) {
client_len = sizeof(client_address);
client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, (socklen_t *)&client_len);
poll_set[numfds].fd = client_sockfd;
poll_set[numfds].events = POLLIN;
numfds++;
update_maxfd(client_sockfd, &max_fd);
printf("Adding client on fd %d\n", client_sockfd);
}
else {
ioctl(poll_set[fd_index].fd, FIONREAD, &nread);
if( nread == 0 )
{
close(poll_set[fd_index].fd);
numfds--;
poll_set[fd_index].events = 0;
printf("Removing client on fd %d\n", poll_set[fd_index].fd);
poll_set[fd_index].fd = -1;
}
else {
read(poll_set[fd_index].fd, &ch, 1);
printf("Serving client on fd %d\n", poll_set[fd_index].fd);
ch++;
write(poll_set[fd_index].fd, &ch, 1);
}
}
}
}
}
}
However, whilst the first to clients connected work ok, the others get 'broken pipe' and I am unsure how to fix this.
Client:
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/un.h>
#include <unistd.h>
#define SOCKET_PATH "web/server_socket.sock"
int main()
{
int sockfd;
int len;
struct sockaddr_un address;
int result;
char ch = 'A';
/* -AF_UNIX is a UNIX internal socket, created on the filesystem.
* -SOCK_STREAM is a reliable, sequenced, connection-based two-way byte stream
* (INET equivalent is TCP) */
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
/* -sun_family - specifies type (domain) of socket
* -sun_path - socket path location (on filesystem) */
address.sun_family = AF_UNIX;
strcpy(address.sun_path, SOCKET_PATH);
len = sizeof(address);
/* request connection from the server, connecting socket to server with specified address
* 'len' is the length of the address */
result = connect(sockfd, (struct sockaddr *)&address, len);
/* exit with error if connection is not successful */
if(result == -1) {
perror("oops: client1");
exit(1);
}
/* otherwise write data to server and obtain response */
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf("char from server: %c\n", ch);
close(sockfd);
exit(0);
}
Thanks in advance
Joshun