版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/84672483
一、情景再现
典型的C/S模式是这样的,不妨以多线程为例来说明:ser启动一个专门用于处理cli连接请求的线程,一旦需要连接,就accept,与cli建立连接,连接好后将事物交付给其他线程去处理。
当我们从事件监听的角度读看待这个流程的话,服务器端起始有两处需要被监听:1、until有了连接请求才去accept;2、连接建立好了之后,until有了数据传输才会有recv或者send操作。
二、代码实现
2.1 服务器端
#include<iostream>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<event.h>
#include<assert.h>
using namespace std;
void listen_cb(int fd, short event, void* arg); //是否需要accept
void c_cb(int clifd, short event, void *arg); //是否需要recv
int main()
{
struct event_base *lib = event_base_new(); //初始化libevent
int fd = socket(AF_INET, SOCK_STREAM, 0);
assert(-1 != fd);
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(6000);
ser.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = bind(fd, (struct sockaddr*)&ser, sizeof(ser));
assert(-1 != res);
assert(-1 != listen(fd, 5));
//创建事件
struct event* listen_event = event_new(lib, fd, EV_READ|EV_PERSIST, listen_cb, lib);
assert(NULL != listen_event);
event_add(listen_event, NULL); //将事件添加到列表中去
event_base_dispatch(lib); //循环监听
return 0;
}
//主要是监听是否要accept()
void listen_cb(int fd, short event, void *arg)
{
struct event_base* lib = (struct event_base*)arg;
struct sockaddr_in cli;
socklen_t len = sizeof(cli);
int clifd = accept(fd, (struct sockaddr*)&cli, &len);
assert(-1 != clifd);
//针对是否需要向已连接的客户端提供服务
struct event* cli_event = event_new(lib, clifd, EV_READ, c_cb, lib);
assert(NULL != cli_event);
event_add(cli_event, NULL);
}
//主要是监听是否要recv或者send
void c_cb(int clifd, short event, void *arg)
{
char buf[128] = {'\0'};
int n = recv(clifd, buf, 127, 0);//一旦连接好的客户端不再发送数据n=0
if(n > 0)
{
cout<<buf<<endl;
assert(-1 != send(clifd, "OK", sizeof("OK"), 0));
}
else
{
close(clifd);
}
}
2.2客户端
#include<iostream>
#include<event.h>
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr()
#include<assert.h>
using namespace std;
int main()
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
assert(-1 != fd);
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(6000);
ser.sin_addr.s_addr = inet_addr("127.0.0.1");
int res= connect(fd, (struct sockaddr*)&ser, sizeof(ser));
assert(-1 != res);
assert(-1 != send(fd, "hello", sizeof("hello"), 0));
char buf[128] = {'\0'};
int n = recv(fd, buf, 127, 0);
if(n > 0);
cout<<buf<<endl;
return 0;
}