这个demo如果需要改进可以提出建议
server
#include <iostream>
#include <sys/select.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <string.h>
#include <event.h>
#include <event2/bufferevent.h>
#include <sys/types.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
using namespace std;
#define SERVER_IP "192.168.5.227"
#define SERVER_PORT 9090
#define BUF_SIZE 1024
void bufferent_event_ok(struct bufferevent *bev, void *arg) {
cout<<"bufferent_event_ok happened ....."<<endl;
evutil_socket_t sfd = bufferevent_getfd(bev);
int recv_size = 0;
char buf[100];
memset(buf,0,sizeof(char)*100);
std::cout<<"enter buf==="<<buf<<std::endl;
if ((recv_size = bufferevent_read(bev, buf, 100)) > 0) // 读取前100位的数据
{
}
std::cout<<"get buf==="<<buf<<std::endl;
std::string str_recv(buf, 5); // 字符串截取前 5位数据
std::cout<<"str_recv=="<<str_recv<<std::endl;
/*实现回显功能*/
int write_num = write(sfd, buf, strlen(buf));
cout << write_num << " characters written" << endl;
}
void bufferent_event_erro3(struct bufferevent *bev, short event, void *arg)
{
evutil_socket_t sfd = bufferevent_getfd(bev);
bufferevent_free(bev);
if (event & BEV_EVENT_TIMEOUT)
{
cout<<"bufferent_event_erro3 happened 1....."<<endl;
}
else if (event & BEV_EVENT_EOF)
{
cout<<"bufferent_event_erro3 happened 2....."<<endl;
int error_code = EVUTIL_SOCKET_ERROR();
cout<<"on_accept_bak happened error_code....."<<error_code<<", description ="<< evutil_socket_error_to_string(error_code)<<endl;
}
else if (event & BEV_EVENT_ERROR)
{
int error_code = EVUTIL_SOCKET_ERROR();
cout<<"on_accept_bak happened error_code....."<<error_code<<", description ="<< evutil_socket_error_to_string(error_code)<<endl;
}
}
void on_accept_bak(int sock, short event, void* arg) {
cout<<"on_accept_bak happened ....."<<endl;
struct event_base* base =static_cast<event_base*> (arg);
evutil_socket_t fd;
struct sockaddr_in sin;
socklen_t slen = sizeof(sin);
/* accept之后 水平触发 消失*/
fd = accept(sock, (struct sockaddr *) &sin, &slen);
if (-1 == fd)
{
std::cout<<"fd error"<<std::endl;
return;
}
/* 测试一下bufferevent*/
int flag = EV_READ | EV_PERSIST;
evutil_make_socket_nonblocking(fd);
struct bufferevent *logic_pro_bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(logic_pro_bev, bufferent_event_ok, NULL, bufferent_event_erro3, NULL);
bufferevent_enable(logic_pro_bev, flag);
}
int main() {
evutil_socket_t fd = socket(AF_INET, SOCK_STREAM, 0);
int flags = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &flags, sizeof(flags)) != 0)
{
close(fd);
return false;
}
if (fd < 0) {
cout << "Error in main(), fd<0" << endl;
}
cout << "main() fd=" << fd << endl;
//----为服务器主线程绑定ip和port------------------------------
struct sockaddr_in local_addr; //服务器端网络地址结构体
memset(&local_addr, 0, sizeof(local_addr)); //数据初始化--清零
local_addr.sin_family = AF_INET; //设置为IP通信
local_addr.sin_addr.s_addr = inet_addr(SERVER_IP); //服务器IP地址
local_addr.sin_port = htons(SERVER_PORT); //服务器端口号
int bind_result = bind(fd, (struct sockaddr*) &local_addr,
sizeof(struct sockaddr));
if (bind_result < 0) {
cout << "Bind Error in main()" << endl;
return -1;
}
cout << "bind_result=" << bind_result << endl;
listen(fd, 50);
//-----设置libevent事件,每当socket出现可读事件,就调用on_accept_bak()------------
struct event_base* base = event_base_new();
assert(base != NULL);
struct event listen_ev_bak;
event_set(&listen_ev_bak, fd, EV_READ | EV_PERSIST, on_accept_bak, base);
event_base_set(base, &listen_ev_bak);
event_add(&listen_ev_bak, NULL);
event_base_dispatch(base);
//------以下语句理论上是不会走到的---------------------------
cout << "event_base_dispatch() in main() finished" << endl;
//----销毁资源-------------
event_del(&listen_ev_bak);
event_base_free(base);
cout << "main() finished" << endl;
}
client.c
#include <iostream>
#include <sys/select.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include <string.h>
#include <event.h>
#include <event2/bufferevent.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
using namespace std;
#define BUF_SIZE 1024
/**
* 连接到server端,如果成功,返回fd,如果失败返回-1
*/
int connectServer(char* ip, int port) {
int fd = socket(AF_INET, SOCK_STREAM, 0);
cout << "fd= " << fd << endl;
if (-1 == fd) {
cout << "Error, connectServer() quit" << endl;
return -1;
}
struct sockaddr_in remote_addr; //服务器端网络地址结构体
memset(&remote_addr, 0, sizeof(remote_addr)); //数据初始化--清零
remote_addr.sin_family = AF_INET; //设置为IP通信
remote_addr.sin_addr.s_addr = inet_addr(ip); //服务器IP地址
remote_addr.sin_port = htons(port); //服务器端口号
int con_result = connect(fd, (struct sockaddr*) &remote_addr,
sizeof(struct sockaddr));
if (con_result < 0) {
cout << "Connect Error!" << endl;
close(fd);
return -1;
}
cout << "con_result=" << con_result << endl;
return fd;
}
void bufferent_event_ok(struct bufferevent *bev, void *arg) {
cout<<"bufferent_event_ok happened ....."<<endl;
evutil_socket_t sfd = bufferevent_getfd(bev);
int recv_size = 0;
char buf[100];
memset(buf,0,sizeof(char)*100);
std::cout<<"enter buf==="<<buf<<std::endl;
if ((recv_size = bufferevent_read(bev, buf, 100)) > 0) // 读取前100位的数据
{
}
std::cout<<"get buf==="<<buf<<std::endl;
std::string str_recv(buf, 5); // 字符串截取前 5位数据
std::cout<<"str_recv=="<<str_recv<<std::endl;
}
void bufferent_event_erro3(struct bufferevent *bev, short event, void *arg)
{
evutil_socket_t sfd = bufferevent_getfd(bev);
bufferevent_free(bev);
if (event & BEV_EVENT_TIMEOUT)
{
cout<<"bufferent_event_erro3 happened 1....."<<endl;
}
else if (event & BEV_EVENT_EOF)
{
cout<<"bufferent_event_erro3 happened 2....."<<endl;
int error_code = EVUTIL_SOCKET_ERROR();
cout<<"on_accept_bak happened error_code....."<<error_code<<", description ="<< evutil_socket_error_to_string(error_code)<<endl;
}
else if (event & BEV_EVENT_ERROR)
{
int error_code = EVUTIL_SOCKET_ERROR();
cout<<"on_accept_bak happened error_code....."<<error_code<<", description ="<< evutil_socket_error_to_string(error_code)<<endl;
}
}
void* init_read_event(void* arg) {
long long_sock = (long) arg;
int sock = (int) long_sock;
//-----初始化libevent,设置回调函数on_read()------------
std::cout<<"create base new show!!!!!!!"<<std::endl;
struct event_base* base = event_base_new();
/**使用bufferevent 来托管 connect 产生的fd**/
int flag = EV_READ | EV_PERSIST;
struct bufferevent *logic_pro_bev = bufferevent_socket_new(base , sock, BEV_OPT_CLOSE_ON_FREE);
if(logic_pro_bev == NULL)
{
return false;
}
bufferevent_setcb(logic_pro_bev, bufferent_event_ok, NULL, bufferent_event_erro3, base);
bufferevent_enable(logic_pro_bev, flag);
event_base_dispatch(base);
event_base_free(base);
std::cout<<"dispatch is over in buffevent"<<std::endl;
}
/**
* 创建一个新线程,在新线程里初始化libevent读事件的相关设置,并开启event_base_dispatch
*/
void init_read_event_thread(int sock) {
pthread_t thread;
pthread_create(&thread, NULL, init_read_event, (void*) sock);
pthread_detach(thread);
}
int main() {
cout << "main started" << endl; // prints Hello World!!!
cout << "Please input server IP:" << endl;
char ip[16];
cin >> ip;
cout << "Please input port:" << endl;
int port;
cin >> port;
cout << "ServerIP is " << ip << " ,port=" << port << endl;
int socket_fd = connectServer(ip, port);
cout << "socket_fd=" << socket_fd << endl;
init_read_event_thread(socket_fd);
//--------------------------
char buffer[BUF_SIZE];
bool isBreak = false;
while (!isBreak) {
cout << "Input your data to server(\'q\' or \"quit\" to exit)" << endl;
cin >> buffer;
if (strcmp("q", buffer) == 0 || strcmp("quit", buffer) == 0) {
isBreak = true;
close(socket_fd);
break;
}
cout << "Your input is " << buffer << endl;
int write_num = write(socket_fd, buffer, strlen(buffer));
cout << write_num << " characters written" << endl;
}
cout << "main finished" << endl;
return 0;
}