client.cpp

// App02.cpp : 定义控制台应用程序的入口点。
//
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <iostream>
#include <thread>
#include <atomic> #ifndef WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif #include <event2/thread.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include <event2/bufferevent_struct.h> std::atomic_bool write_over; void eventcb(struct bufferevent *bev, short events, void *ptr)
{
if (events & BEV_EVENT_CONNECTED)
{
/* We're connected to 127.0.0.1:8080. Ordinarily we'd do
something here, like start reading or writing. */
}
else if (events & BEV_EVENT_ERROR)
{
/* An error occured while connecting. */
}
} //接收Server来的消息
static void conn_readcb(struct bufferevent *bev, void *user_data)//arg1:发生了事件的bufferevent,最后一个是用户提供的参数,可以通过这个向回调传递参数
{
char buf[] = {};
int len = bufferevent_read(bev, buf, sizeof(buf));
std::cout<<"来自Server:"<< buf << std::endl;
} static void conn_writecb(struct bufferevent *bev, void *user_data)
{
write_over = true;
//int ret = bufferevent_write(bev, "我是一个客户端!", 20);
} struct event_base *g_base;//管理事件 int main()
{
write_over = false;
struct bufferevent *bev;
struct sockaddr_in sin;
#ifdef WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
//event支持多线程的初始化函数
if(- == evthread_use_windows_threads())
return false; g_base = event_base_new(); memset(&sin, , sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */
sin.sin_port = htons(); /* Port 9527 */ bev = bufferevent_socket_new(g_base, -, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);//创建基于套接字的bufferevent // bufferevent_setcb(bev, NULL, NULL, eventcb, NULL); if (bufferevent_socket_connect(bev,//connect套接字
(struct sockaddr *)&sin, sizeof(sin)) < )
{
/* Error starting connection */
std::cout<<"连接失败!\n";
bufferevent_free(bev);
return -;
}
bufferevent_setcb(bev, conn_readcb, /*conn_writecb*/nullptr, eventcb, "回调参数");//修改回调
bufferevent_enable(bev, EV_READ | EV_WRITE ); std::thread th([]
{
event_base_dispatch(g_base);//循环处理事件
}); int ret = bufferevent_write(bev, "我是客户端-1", ); std::cout<<"输入你想发送的内容:\n";
int count = ;
while()
{
// if(write_over)
{
write_over = false;
char msg[] = {};
sprintf(msg, "第%d次发送信息!", ++count);
bufferevent_write(bev, msg, strlen(msg) + );
Sleep();
}
// Sleep(50);
} th.join();
std::cout<<" over!\n";
getchar();
return ;
}

server.cpp

// App01.cpp : 定义控制台应用程序的入口点。
//
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#ifndef WIN32
#include <netinet/in.h>
# ifdef _XOPEN_SOURCE_EXTENDED
# include <arpa/inet.h>
# endif
#include <sys/socket.h>
#endif #include <event2/thread.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event.h>
#include <event2/bufferevent_struct.h>
#include <thread>
#include <iostream>
#include <vector> /* 设置计数,只允许echo_write_cb调用一次 */
static int count = ;
static std::vector<struct bufferevent *> g_bev;//bufferevent缓冲区 /*当有数据可读的时候,会调用这个函数 */
//读取回调函数
static void echo_read_cb(struct bufferevent *bev, void *ctx)
{
printf("读:echo_read_cb is called\n");
char bufs[] = {};
bufferevent_read(bev, bufs, sizeof(bufs));
std::cout<< bufs <<"\n";
return; printf("读:echo_read_cb is called\n");
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev); size_t len = evbuffer_get_length(input);
printf("evbuffer input length is: %lu\n", (unsigned long)len); //evbuffer_add_buffer(output, input); char buf[];
int n;
n = evbuffer_remove(input, buf, sizeof(buf));
printf("copy bytes == %d\n", n);
printf("copy buf: %s\n", buf);
} //写入回调函数
static void echo_write_cb(struct bufferevent *bev, void *ctx)
{ printf("写:echo_write_cb is called\n");
char sendbuffer[] = "yes, i recv your message!\n";
return; struct evbuffer *output = bufferevent_get_output(bev); if(count == )
{
int result = evbuffer_add(output, sendbuffer, strlen(sendbuffer));
printf("evbuffer_add result = %d\n", result);
} count++;
int len = evbuffer_get_length(output);
evbuffer_drain(output, len);
} /*当客户端结束的时候,肯定会调用这个函数 */
//事件回调函数
static void echo_event_cb(struct bufferevent *bev, short events, void *ctx)
{
printf("状态:echo_event_cb is called\n");
if(events & BEV_EVENT_ERROR)
perror("Error from bufferevent");
if(events & BEV_EVENT_EOF | BEV_EVENT_ERROR)
{
bufferevent_free(bev);
printf("bufferevent_free is called\n");
}
printf("-------------------------------\n\n"); } //client连接回调
static void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd,
struct sockaddr*address, int socklen, void *ctx)
{
printf("连接:Accept_conn_cb is called\n");
struct event_base *base = evconnlistener_get_base(listener);//返回监听器关联的event_base
struct bufferevent *bev = bufferevent_socket_new(base, fd,//创建基于套接字的bufferevent
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_THREADSAFE);
if (!bev)
{
fprintf(stderr, "Error constructing bufferevent!");
event_base_loopbreak(base);
return ;
}
g_bev.push_back(bev); bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, "Server参数");//设置读回调,错误事件回调,null表示禁止回调,cbarg向回调传递参数 bufferevent_enable(bev, EV_READ|EV_WRITE); //开启缓冲区上的读,写事件
} //连接监听器错误回调函数
static void accept_error_cb(struct evconnlistener *listener, void *ctx)
{
printf("监听错误:Accept_error_cb is called\n");
struct event_base *base = evconnlistener_get_base(listener);
int err = EVUTIL_SOCKET_ERROR();
fprintf(stderr, "Got an error"); event_base_loopexit(base, NULL); } struct event_base *g_base; int main(int argc, char **argv)
{
struct evconnlistener *listener;
struct sockaddr_in sin; int port = ; if(argc > )
{
port = atoi(argv[]);
}
if(port <= || port > )
{
puts("Invalid port");
return ;
}
#ifdef WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);//启动异步socket
#endif
if(- == evthread_use_windows_threads())//event多线程支持
return false; g_base = event_base_new();//创建一个event_base
if(!g_base)
{
puts("could't open event_base");
return ;
} memset(&sin, , sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl();
sin.sin_port = htons(port);
//分配返回一个监听器对象,有连接会回调accept_conn_cb函数,绑定iP,port
listener = evconnlistener_new_bind(g_base, accept_conn_cb, NULL,
LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -,
(struct sockaddr*)&sin, sizeof(sin));
if(!listener)
{
perror("could't not create listener");
return ;
} evconnlistener_set_error_cb(listener, accept_error_cb);//侦听错误
std::thread th([]
{
event_base_dispatch(g_base);//程序进入无线循环,等待就绪事件并执行事件处理
});
int count = ;
for(;;)
{
if(!g_bev.empty())
{
for(auto it : g_bev)
{
char msg[] = {};
sprintf(msg, "欢迎!Server send!%d", count);
bufferevent_write(it, msg, );//想缓冲区添加数据
}
count++;
}
Sleep();
}
th.join();
return ;
}

//每个bufferevent有两个数据相关的回调:一个读取回调和一个写入回调。
//默认情况下,从底层传输端口读取了任意量的数据之后会调用读取回调;
//输出缓冲区中足够量的数据被清空到底层传输端口后写入回调会被调用。
//通过调整bufferevent的读取和写入“水位(watermarks)”可以覆盖这些函数的默认行为。

libevent(2)的更多相关文章

  1. linux下libevent安装

    wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz tar –xzvf libevent-1.4.13-stable.tar.gz ...

  2. 总结libevent安装方法

    1.先用:ls -al /usr/lib | grep libevent  查看是否已安装,如果已安装且版本低于1.3,则先通过:rpm -e libevent -nodeps 进行卸载. 2.下载l ...

  3. 定时器管理:nginx的红黑树和libevent的堆

    libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...

  4. [译]libev和libevent的设计差异

    本文译自what's the difference between libev and libevent? 作者是libev作者 [问]两个库都是为异步io调度而设计,在Linux上都是使用epoll ...

  5. Libevent的IO复用技术和定时事件原理

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  6. Libevent初探

    Libevent 是一个用C语言编写的.轻量级的开源高性能网络库,主要有以下几个亮点:事件驱动( event-driven),高性能;轻量级,专注于网络,不如 ACE 那么臃肿庞大:源代码相当精炼.易 ...

  7. PHP写的异步高并发服务器,基于libevent

    PHP写的异步高并发服务器,基于libevent 博客分类: PHP PHPFPSocketLinuxQQ  本文章于2013年11月修改. swoole已使用C重写作为PHP扩展来运行.项目地址:h ...

  8. libevent在windows平台下通过vs进行编译

    1.vs中新建一个静态库项目 2.配置头文件目录,将./compat../include../WIN32-Code三个目录添加到文件目录中 3.用记事本打开Makefile.nmake文件,可以看到里 ...

  9. 基于Libevent的HTTP Server

    简单的Http Server 使用Libevent内置的http相关接口,可以很容易的构建一个Http Server,一个简单的Http Server如下: #include <event2/e ...

  10. windows下编译及使用libevent

    Libevent官网:http://libevent.org/ windows 7下编译: 编译环境: windows 7 + VS2010 (1)解压libevent到F:\libevent\lib ...

随机推荐

  1. Getting started with Chrome Dev Editor

    转自:https://github.com/GoogleChrome/chromedeveditor/blob/master/doc/GettingStarted.md Installation In ...

  2. Sqlldr导入txt文件内容到数据库中

    需求:数据迁移,将txt文件中的内容导入oracle数据库的表中,文本文件中数据格式如下(数据以空格隔开) 1. 创建与文本数据格式相匹配的表(此处在scott用户下创建) create table ...

  3. C# 操作ini配置文件

    最近使用Winform做一个小系统,由于需要保存一些默认配置项.自然就想到了轻量级的配置文件类型ini.在此也分享和记录一下实现方式,方便以后查询和使用. 废话不多说上代码: 实现公共函数↓ publ ...

  4. Vmware虚拟机三种网络模式详解(转)

    原文来自http://note.youdao.com/share/web/file.html?id=236896997b6ffbaa8e0d92eacd13abbf&type=note 我怕链 ...

  5. 测试的一些基本概念知识(TCP )

    一.TCP报头部中的SYN.FIN.ACK: ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1. SYN(SYNchronization) : 在连接建 ...

  6. Android_JarZip压缩和解压文件

        本文资料来自<android开发权威指南> AndroidSDK中提供了java.util.jar和java.util.zip包中的若干类和接口来完成. 压缩文件基本步骤: 1.创 ...

  7. Linux上寻找并杀死僵尸进程

    转载: http://blog.csdn.net/shanzhizi/article/details/47320595 linux服务器上,多少会出现一些僵尸进程,下面介绍如何快速寻找和消灭这些僵尸进 ...

  8. php面象对象魔术方法的使用

    class Moshu{ public $number; public function __construct($str)//构造方法,new实例时,自动调用 { //require('/confi ...

  9. php get_called_class()函数与get_class函数的区别

    get_class (): 获取当前调用方法的类名: get_called_class():获取静态绑定后的类名: 有例为证: class Foo{ public function test(){ v ...

  10. Vivado Logic Analyzer的使用

    chipscope中,通常有两种方法设置需要捕获的信号.1.添加cdc文件,然后在网表中寻找并添加信号2.添加ICON.ILA和VIO的IP Core 第一种方法,代码的修改量小,适当的保留设计的层级 ...