epoll例程

gdb调试遇到 “Address already in use” 处理: netstat -napt 查看对应的端口号的pid,然后 kill -9 pid

 

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/epoll.h>
#include "myutils.h"

/*#define handle_error(status, msg) \
do { if(status == -1) { \
perror(msg); \
exit(EXIT_FAILURE); }\
} while (0)*/

void errcheck(int s, char* str)
{
if((s == -1) &&(str != NULL)) {
perror(str); //printf(“error: %s(errno: %d)\n", strerrno), errno);
abort();
}
else {
return;
}
}

int create_and_bind(char* sport)
{
int listenfd, s;
struct sockaddr_in servaddr;

listenfd = socket(AF_INET, SOCK_STREAM, 0);
errcheck(listenfd, "socket()");
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(atoi(sport));


//solve the bind error:Address already in use
int val = 1;
s = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&val, sizeof(int));
handle_error(s, "setsockopt SO_REUSEADDR");

s = bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
handle_error(s, "bind");

return listenfd;
}


static int make_socket_non_blocking(int sfd)
{
int flags, s;

flags = fcntl(sfd, F_GETFL,0);
if(flags == -1) {
perror("fcntl");
return -1;
}

flags |= O_NONBLOCK;
s = fcntl(sfd, F_SETFL, flags);
if(s == -1) {
perror("fcntl SET");
return -1;
}

return 0;
}


#define MAXEVENTS 64
//#define NI_MAXHOST 512
//#define NI_MAXSERV 512

int main(int argc, char* argv[])
{
int sfd, s;
int efd;
struct epoll_event event;
struct epoll_event *events;

if(argc != 2) {
fprintf(stderr, "Usage: %s [port]\n", argv[0]);
exit(EXIT_FAILURE);
}

sfd = create_and_bind(argv[1]);
if(sfd == -1) {
abort();
}

s = make_socket_non_blocking(sfd);
if(s == -1) {
fprintf(stdout, "mack socket nonblocking failed\n");
abort();
}


s = listen(sfd, SOMAXCONN);
if(s == -1) {
perror("listen");
abort();
}

efd = epoll_create(1);
if(efd == -1) {
perror("epoll_create");
abort();
}

event.data.fd = sfd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
errcheck(s, "epoll_ctl");

//Buffer where events are returne
events = calloc(MAXEVENTS, sizeof(event));

//The event loop
while (1) {
int n, i;

n = epoll_wait(efd, events, MAXEVENTS, -1); // timeout -1 means wait indefinitely
for(i = 0; i < n; i++) {
if((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN))) {
fprintf(stderr, "epoll_wait error\n");
close(events[i].data.fd);
continue;
}
else if(sfd == events[i].data.fd) {
while(1) {
struct sockaddr in_addr;
socklen_t in_len;
int infd;
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

in_len = sizeof(in_addr);
infd = accept(sfd, &in_addr, &in_len); //in_addr. ip address and port of the connected client
if(infd == -1) {
if((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
//we have processed all incoming connections
break;
}
else {
perror("accept");
break;
}
}

s = getnameinfo(&in_addr, in_len, hbuf, sizeof(hbuf), sbuf,sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
if(s == 0) {
printf("Accepted connection on fd %d, client host = %s, port = %s\n", infd,hbuf,sbuf);
}

s = make_socket_non_blocking(infd);
if(s == -1) {
abort();
}

event.data.fd = infd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
errcheck(s,"epoll_ctl accept");
}
continue;
}
else {
// We have data on the fd waiting to be read. We must read watever data is available completely. as we are running in edge-triggered mode
//and won't get a notification again for the same data.
int done = 0;

while(1) {
ssize_t count;
char buf[512];
count = read(events[i].data.fd, buf, sizeof(buf));
if(count == -1) {
/*If errno == EAGAIN, that means we have read all data. so go back to the main loop. */
if(errno != EAGAIN) {
perror("read infd");
done = 1;
}
break;
}
else if(count == 0) {
/*End of file. The remote has closed the connection*/
done = 1;
break;
}

/*Write the buffer to standard outputi--fd = 1*/
/*if((int)buf[count-1] == '\n') {
buf[count-1] = 0;
}*/
s = write(1, buf, count);
s = write(events[i].data.fd, buf, count);
errcheck(s, "write infd");
}
if(done) {
printf("Closed connection on descriptor %d\n", events[i].data.fd);
/*Closing the descriptor will make epoll remove it from the set of descriptors which are monitored*/
close(events[i].data.fd);
}
}
} //end for()
} //end while
free(events);
close(sfd);
return EXIT_SUCCESS;
}

 

posted @ 2021-08-15 12:32  平安1111  阅读(96)  评论(0)    收藏  举报