I am trying to implement a chat program using epoll on the server side. However, the program gets stuck at epoll_wait(). How should I create an asynchronous chat program?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <netdb.h>
#include <unistd.h>
#define MAX_BUF 30;
int
setnonblocking(int sock)
{
int opts;
opts = fcntl(sock,F_GETFL);
if (opts < 0) {
perror("fcntl(F_GETFL)");
exit(EXIT_FAILURE);
}
opts = (opts | O_NONBLOCK);
if (fcntl(sock,F_SETFL,opts) < 0) {
perror("fcntl(F_SETFL)");
exit(EXIT_FAILURE);
}
return 0;
}
int
main() {
char buf[30];
printf("server is starting\n");
struct epoll_event ev, events[10];
int write_sock, nfds, epollfd, n, err;
const char *str = "hello from the server";
struct sockaddr_in my_addr;
memset(&my_addr, 0, sizeof(struct sockaddr_in));
//Declaring process variables.
int server_sockfd;
int server_len;
struct sockaddr_in server_address;
//Remove any old socket and create an unnamed socket for the server.
struct addrinfo hints;
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_STREAM; /* We want a TCP socket */
hints.ai_flags = AI_PASSIVE; /* All interfaces */
struct addrinfo *res;
char *listen_port = "7734";
err = getaddrinfo (NULL, listen_port, &hints, &res);
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_port = htons(7734);
server_address.sin_addr.s_addr= res->ai_addr;
server_len = sizeof(server_address);
bind(server_sockfd, (struct sockaddr *) res->ai_addr, res->ai_addrlen);
setnonblocking(server_sockfd);
//Create a connection queue and wait for clients
if (listen(server_sockfd, 5) < 0) {
perror("bind: ");
}
epollfd = epoll_create(10);
if (epollfd == -1) {
perror("epoll_create");
exit(EXIT_FAILURE);
}
else
printf("epoll created\n");
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT;
ev.data.fd = server_sockfd;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, server_sockfd , &ev) == -1) {
perror("epoll_ctl: server_sockfd");
exit(EXIT_FAILURE);
}
else
printf("epollctl is done, entering while\n");
int t;
struct sockaddr local;
socklen_t addrlen;
str="hello world!";
while(1) {
nfds = epoll_wait(epollfd, events, 10, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
for(n = 0; n < nfds; ++n) {
if(events[n].data.fd == server_sockfd) {
write_sock = accept(server_sockfd,(struct sockaddr *) &server_address, &server_len);
if(write_sock < 0)
{
perror("accept");
exit(EXIT_FAILURE);
}
else
printf("connection accepted, executing non blocking\n");
setnonblocking(write_sock);
printf("returned from nonblocking\n");
printf("sending\n");
t=strlen(str);
err = send(write_sock, str, t,0);
printf("the result of send is %d \n",err);
if (err == -1) {
printf("error on send (errno=%d)\n", errno);
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, write_sock,&ev) == -1) {
perror("epoll_ctl: write_sock");
exit(EXIT_FAILURE);
} }
else if(err == 0)
printf("data has been sent\n");
}
}
n=0;
while(1)
{ nfds = epoll_wait(epollfd, events, 10, -1);
if (nfds == -1) {
perror("epoll_pwait");
exit(EXIT_FAILURE);
}
if (events[n].events & EPOLLIN) {
printf("waiting for data\n");
err = recv(write_sock, buf, 30 , 0);
if (err == -1)
{ perror("read");
exit(EXIT_FAILURE);}
else
printf(" read %d bytes: %.*s\n", err, err, buf);
}
else if(events[n].events & EPOLLOUT) {
printf("input data to write\n");
scanf("%s",&buf);
if(*buf == 'q')
break;
err=send(write_sock, buf, 30, 0);
if(err == -1){
perror("write");
exit(EXIT_FAILURE);}
else printf("write %d bytes: %.*s\n", err, err, buf);
}
}
}
}