实现功能:client从标准输入读取输入,发送到server;server收到client的消息后,原样发给client。
libev simple server
/*
* example_server.c
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <netinet/in.h>
#include <strings.h>
#include "ev.h"
#define PORT 8333
#define BUFFER_SIZE 1024
#define MAX_ALLOWED_CLIENT 10240
struct ev_io *libevlist[MAX_ALLOWED_CLIENT] = { NULL };
// gcc example_server.c ev.o -lm
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);
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);
struct ev_io socket_watcher;
ev_timer timeout_watcher;
if ((sd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
printf("socket error. errno:%d\n", errno);
return -1;
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0)
{
printf("bind error.errno:%d\n", errno);
}
if (listen(sd, 2) < 0)
{
printf("listen error\n");
return -1;
}
printf("ev_loop beg\n");
ev_io_init(&socket_watcher, accept_cb, sd, EV_READ);
ev_io_start(loop, &socket_watcher);
printf("ev_loop start\n");
ev_loop(loop, 0);
printf("ev_loop end\n");
return 0;
}
void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_sd;
struct ev_io *w_client = (struct ev_io*) malloc(sizeof(struct ev_io));
if (EV_ERROR & revents)
{
printf("error event in accept\n");
return;
}
client_sd = accept(watcher->fd, (struct sockaddr *) &client_addr,
&client_len);
if (client_sd < 0)
{
printf("accept error\n");
return;
}
//如果连接数超出指定范围,则关闭连接
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("someone connected.\n");
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");
return;
}
read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
if (read < 0)
{
printf("read error,errno:%d\n", errno);
return;
}
if (read == 0)
{
printf("someone disconnected, errno:%d\n", errno);
freelibev(loop, watcher->fd);
return;
}
else
{
printf("get the message:%s\n", buffer);
}
send(watcher->fd, buffer, read, 0);
bzero(buffer, read);
}
int freelibev(struct ev_loop *loop, int fd)
{
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;
}
libev simple client
/*
* example_client.c
*
*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "ev.h"
#define PORT 8333
#define BUFFER_SIZE 1024
// gcc example_client.c ev.o -lm
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);
void stdin_cb(EV_P_ ev_io *w, int revents);
int g_server_sockfd;
int main()
{
struct ev_loop *loop = ev_default_loop(0);
struct hostent *he; /* 主机信息 */
struct sockaddr_in their_addr; /* 对方地址信息 */
/* get the host info */
if ((he = gethostbyname("127.0.0.1")) == NULL)
{
/* 注意:获取DNS信息时,显示出错需要用herror而不是perror */
herror("gethostbyname");
exit(1);
}
if ((g_server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT); /* short, NBO */
their_addr.sin_addr = *((struct in_addr *) he->h_addr);
bzero(&(their_addr.sin_zero), 8); /* 其余部分设成0 */
if (connect(g_server_sockfd, (struct sockaddr *) &their_addr,
sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
ev_io w_client;
ev_io_init(&w_client, read_cb, g_server_sockfd, EV_READ);
ev_io_start(loop, &w_client);
ev_io stdin_watcher;
ev_io_init(&stdin_watcher, stdin_cb, STDIN_FILENO, EV_READ);
ev_io_start(loop, &stdin_watcher);
printf("ev_loop start\n");
ev_loop(loop, 0);
printf("ev_loop end\n");
close(g_server_sockfd);
return 0;
}
void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
{
char buffer[BUFFER_SIZE];
ssize_t len;
if (EV_ERROR & revents)
{
printf("error event in read");
return;
}
len = recv(watcher->fd, buffer, BUFFER_SIZE, 0);
if (len < 0)
{
printf("network read error,errno:%d\n", errno);
return;
}
if (len == 0)
{
printf("someone disconnected.errno:%d\n", errno);
close(watcher->fd);
ev_io_stop(loop, watcher);
free(watcher);
return;
}
else
{
printf("get the message:%s\n", buffer);
if (strcmp("quit", buffer) == 0)
{
ev_io_stop(EV_A_ watcher);
// to stop network io event
ev_break(EV_A_ EVBREAK_CANCEL);
}
}
}
void stdin_cb(EV_P_ ev_io *w, int revents)
{
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
ssize_t len;
if (EV_ERROR & revents)
{
printf("error event in read");
return;
}
// w->fd: STDIN_FILENO
// len = recv(w->fd, buffer, sizeof(buffer), 0); // wrong??
len = read(w->fd, buffer, sizeof(buffer)); // right
if (len <= 0)
{
printf("stdin read error, return:%ld, errno:%d\n", len, errno);
return;
}
if ('\n' == buffer[len-1])
{
buffer[len-1] = '\0';
if ('\r' == buffer[len-2])
{
buffer[len-2] = '\0';
len--;
}
}
send(g_server_sockfd, buffer, len, 0);
if (strcmp("quit", buffer) == 0)
{
ev_io_stop(EV_A_ w);
// to stop network io event
ev_break(EV_A_ EVBREAK_CANCEL);
}
bzero(buffer, len);
}