Use the C language version of libev to implement a simple network communication server

Source: Internet
Author: User

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


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.