Due to the recent epoll version of the server, there have been some strange problems, and it is necessary to use libev to go online quickly. Here, we will record a simple use case. There may be some bugs in the code. This code is not a code that runs online, but it is already well-organized. If you have any questions, please discuss it.
#include <ev.h>
#include <stdio.h>
#include <netinet/in.h>
#include<stdlib.h>
#include <string.h>
#define PORT 57789
#define BUFFER_SIZE 2048
#define MAX_ALLOWED_CLIENT 10240
Struct ev_io *libevlist[MAX_ALLOWED_CLIENT] = {NULL};
Void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
Void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
Void timer_beat(struct ev_loop *loop, struct ev_timer *watcher, int revents);
Int freelibev(struct ev_loop *loop, int fd);
Int main()
{
Struct ev_loop *loop=ev_default_loop(0);
Int sd;
Struct sockaddr_in addr;
Int addr_len = sizeof(addr);
/ / Create an io watcher and a timer watcher
Struct ev_io socket_accept;
Struct ev_timer timeout_w;
/ / Create a socket connection
Sd = socket(PF_INET, SOCK_STREAM, 0);
If(sd < 0)
{
Printf("socket error\n");
Return -1;
}
Bzero(&addr, sizeof(addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(PORT);
Addr.sin_addr.s_addr = INADDR_ANY;
//normal bind
If(bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
Printf("bind error\n");
Return -1;
}
//Normal listen
If(listen(sd, SOMAXCONN) < 0)
{
Printf("listen error\n");
Return -1;
}
/ / Set fd can be reused
Int bReuseaddr=1;
If(setsockopt(sd,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(bReuseaddr)) != 0)
{
Printf("setsockopt error in reuseaddr[%d]\n", sd);
Return ;
}
/ / Initialize io watcher, used to listen to fd
Ev_io_init(&socket_accept, accept_cb, sd, EV_READ);
Ev_io_start(loop, &socket_accept);
/ / Can send heartbeat packets to the far end
//ev_timer_init(&timeout_w, timer_beat, 1., 0.);
//ev_timer_start(loop, &timeout_w);
Ev_run(loop, 0);
Return 1;
}
Void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
/*
If there is a link, continue to listen to fd;
*/
Struct sockaddr_in client_addr;
Socklen_t client_len = sizeof(client_addr);
Int client_sd;
/ / Create a client's io watcher
Struct ev_io *w_client = (struct ev_io*) malloc(sizeof(struct ev_io));
If(w_client == NULL)
{
Printf("malloc error in accept_cb\n");
Return ;
}
If(EV_ERROR & revents)
{
Printf("error event in accept\n");
Return ;
}
/ / Get the fd connected to the client
Client_sd = accept(watcher->fd, (struct sockaddr*)&client_addr, &client_len);
If(client_sd < 0)
{
Printf("accept error\n");
Return;
}
/ / If the number of connections is outside the specified range, close the connection
If( client_sd > MAX_ALLOWED_CLIENT)
{
Printf("fd too large[%d]\n", client_sd);
Close(client_sd);
Return ;
}
If(libevlist[client_sd] != NULL)
{
Printf("client_sd not NULL fd is [%d]\n", client_sd);
Return ;
}
Printf("client connected\n");
/ / Monitor new fd
Ev_io_init(w_client, read_cb, client_sd, EV_READ);
Ev_io_start(loop, w_client);
Libevlist[client_sd] = w_client;
}
Void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
Char buffer[BUFFER_SIZE];
Ssize_t read;
If(EV_ERROR & revents)
{
Printf("error event in read\n");
Return ;
}
//Normal recv
Read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
If(read < 0)
{
Printf("read error\n");
Return;
}
If(read == 0)
{
Printf("client disconnected.\n");
//ev_io_stop(loop, watcher);
//free(watcher);
/ / If the client disconnects, release the response resource, and close the listener
Freelibev(loop, watcher->fd);
Return;
}
Else
{
//buffer[read] = '\0';
Printf("receive message:%s\n", buffer);
}
/ / Return to the client
Send(watcher->fd, buffer, read, 0);
Bzero(buffer, read);
}
Void timer_beat(struct ev_loop *loop, struct ev_timer *watcher, int revents)
{
Float timeout = 2.0;
//You can send a heartbeat packet here, or you can do nothing.
Printf("send beat per[%f]\n",timeout);
Fflush(stdout);
If(EV_ERROR & revents)
{
Printf("error event in timer_beat\n");
Return ;
}
Ev_timer_set(watcher, timeout,0.);
Ev_timer_start(loop, watcher);
Return;
}
Int freelibev(struct ev_loop *loop, int fd)
{
/*if(fd > MAX_ALLOWED_CLIENT)
{
Printf("more than MAX_ALLOWED_CLIENT[%d]", fd);
Return -1;
}*/
/ / Clean up related resources
If(libevlist[fd] == NULL)
{
Printf("the fd already freed[%d]\n", fd);
Return -1;
}
Close(fd);
Ev_io_stop(loop, libevlist[fd]);
Free(libevlist[fd]);
Libevlist[fd] = NULL;
Return 1;
}
makefile:
CC=gcc
FLAGS=-I. -I/home/lengzijian/c/libev/libev-4.11
LDFLAGS=-L/usr/lib -L/home/lengzijian/c/libev/libev-4.11/.libs -lev -Wall
OBJECTS=server.o
ALL_BIN=server
all:$(ALL_BIN)
$(ALL_BIN):$(OBJECTS)
$(CC) $(FLAGS) $(LDFLAGS) -o $@ $^
%.o:%.c
$(CC) -c $< $(FLAGS) $(FLAGS)
clean:
rm -fr $(OBJECTS)
rm -fr $(ALL_BIN)
Note the header file path in the makefile, and the path to the dynamic link library
When testing, you only need telnet ip 57789