文章目录
- 一、功能介绍
- 二、服务器和客户端通信架构
- 三、详细代码
- 四、测试效果
一、功能介绍
- 1)使用libevent库实现客户端和服务器的连接;
- 2)实现回显功能:
①在窗口输入字符串到客户端‘
②客户端发送字符到服务器;
③服务器接收到字符后,将字符转换成大写;
④服务器将大写字符发送给客户端;
⑤客户端显示大写字符。
二、服务器和客户端通信架构
1、服务器
- 1)创建event_base。
- 2)创建服务器连接监听器 evconnlistener_new_bind,这个函数相当于完成了socket、bind、listen、accept函数的功能。与客户端成功连接后,连接监听器的回调函数被调用。将会获得socket的fd。
- 3)在连接监听器回调函数中,使用bufferevent_socket_new()创建一个新bufferevent事件,将fd封装到这个事件对象中。
- 4)在连接监听器回调函数中,使用bufferevent_setcb() ,给这个新的bufferevent事件设置read、write、event回调函数。在read回调函数中实现大小写转换。
- 5)在连接监听器回调函数中,设置bufferevent的读写缓冲区,bufferevent_endisable()。
- 6)接收、发送数据用到的函数:bufferevent_read()、bufferevent_write()。
- 7)启动循环 event_base_dispatch();用来监听事件。
- 8)释放资源。
2、客户端
- 1)创建fd——》socket()函数。
- 2)创建event_base.
- 3)使用bufferevent_socket_new()创建一个跟服务器通信的bufferevent事件对象。
- 4)使用bufferevent设置bufferevent事件的回调函数。读回调函数用来回显服务器返回的大写字符串。
- 5)设置bufferevent的读写缓冲器 bufferevent_enable()。
- 6)使用bufferevent_socket_connect() 连接服务器。需要定义一个struct sockaddr_in类型的对象。
- 7)使用event_new()函数创建一个事件对象。文件描述符是STDIN_FILENO。用于监听窗口输入的字符串。它的回调函数用来实现读取缓冲区read(),然后将字符串发送给服务器bufferevent_write()。
- 8)添加事件event_add()。
- 9)启动循环监听event_base_dispatch()。
- 10)释放资源
三、详细代码
1、服务器代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERV_PORT 666
static void read_cb (struct bufferevent *bev, void *ctx)
{
char buf[1024] = {0};
int n = 0;
n = bufferevent_read (bev, buf, sizeof(buf));
for (int i=0; i<n; i++)
buf[i] = toupper(buf[i]);
printf ("%s", buf);
bufferevent_write (bev, buf, n);
}
static void listen_cb (struct evconnlistener *listener,
evutil_socket_t fd,
struct sockaddr* address,
int socketlen,
void *ctx)
{
struct event_base *base = evconnlistener_get_base (listener);
struct bufferevent *bev = bufferevent_socket_new (
base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb (bev, read_cb, NULL, NULL, NULL);
bufferevent_enable (bev, EV_READ|EV_WRITE);
printf ("connect successful\n");
}
int main (void)
{
struct event_base *base;
struct evconnlistener *listen_event;
struct sockaddr_in seraddr;
bzero (&seraddr, sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons (SERV_PORT);
seraddr.sin_addr.s_addr = htonl (INADDR_ANY);
base = event_base_new();
listen_event = evconnlistener_new_bind (base, listen_cb, NULL,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
-1,
(struct sockaddr*)&seraddr,
sizeof(seraddr));
event_base_dispatch (base);
event_base_free (base);
evconnlistener_free (listen_event);
return 0;
}
2、客户端代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 666
static void read_cb (struct bufferevent *bev, void *ctx)
{
char buf[1024] = {0};
bufferevent_read (bev, buf, sizeof(buf));
printf ("%s", buf);
memset (buf, '\0',1024);
}
static void event_read_cb (evutil_socket_t fd, short what, void *arg)
{
char buf[1024] = {0};
int n = 0;
struct bufferevent *bev = (struct bufferevent *)arg;
n = read (fd, buf, sizeof(buf));
bufferevent_write(bev, buf, n+1);
}
int main (void)
{
struct event_base *base;
struct bufferevent *bev;
struct event *ev;
struct sockaddr_in sin;
int fd;
fd = socket(AF_INET, SOCK_STREAM, 0);
base = event_base_new ();
bev = bufferevent_socket_new (base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb (bev, read_cb,NULL, NULL, NULL);
bufferevent_enable (bev, EV_READ);
sin.sin_family = AF_INET;
sin.sin_port = htons (SERVER_PORT);
inet_pton (AF_INET,"127.0.0.1", &sin.sin_addr.s_addr);
bufferevent_socket_connect (bev, (struct sockaddr*)&sin, sizeof(sin));
ev = event_new (base, STDIN_FILENO, EV_READ|EV_PERSIST, event_read_cb, bev);
event_add (ev, NULL);
event_base_dispatch (base);
bufferevent_free(bev);
event_base_free (base);
event_free (ev);
return 0;
}
四、测试效果