libevent实现服务端客户端的回显功能

来源:互联网 发布:怎样利用网络学英语 编辑:程序博客网 时间:2024/06/11 02:39

这个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 1024void 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;}



阅读全文
0 0
原创粉丝点击