client.cpp
#include "co_routine.h"
#include::connect(fd, (struct sockaddr *)&remote, sizeof(remote));
connpool.push(fd);
}
}
void * client(void *arg)
{
co_enable_hook_sys();
STask *co = (STask *)arg;
int fd = 0;
while(1)
{
if(connpool.empty())
poll(0,0,1);
if(!connpool.empty())
{
fd = connpool.top();
connpool.pop();
break;
}
}
int sbuflen = 256;//只能是栈上变量..
char buf[ sbuflen ];
char recvb[sbuflen];
int index = 0;
for(;;)
{
int ret = sprintf(buf, "fd:%d index:%d", fd, index++);
send(fd, buf, ret + 1, 0);
int rret = recv(fd, recvb, sizeof(recvb), 0);
LOGD("%s\n", recvb);
recvb[0] = 0;
++gcount;
}
return 0;
}
void * timeout_coroutine(void *priv)
{
co_enable_hook_sys();
for (;;)
{
poll(0, 0, 1000);//sleep 1s; release cpu... not yield...
LOGI("run %d times in 1s\n", gcount);
gcount = 0;
}
}
void run()
{
arrayTask = new STask[2 + cocount];
co_create(&arrayTask[0].pCo, NULL, init_pool, &arrayTask[0]);
co_resume(arrayTask[0].pCo);
for(int i = 1; i < 1 + cocount; i++)
{
co_create(&arrayTask[i].pCo, NULL, client, &arrayTask[i]);
co_resume(arrayTask[i].pCo);
}
co_create(&arrayTask[1+cocount].pCo, NULL, timeout_coroutine, &arrayTask[1+cocount]);
co_resume(arrayTask[1+cocount].pCo);
co_eventloop(co_get_epoll_ct(), 0, 0);
LOGD("end of run...\n");
}
int main(int, char *[])
{
run();
return 0;
}
server.cpp
#include "co_routine.h"
#include
#include
#include "util.h"
#include
#include
#include
#include
using namespace std;
class STask
{
public:
stCoRoutine_t *pCo;
int fd;
STask(){
pCo = NULL;
fd = -1;
}
};
int cocount = 2;
STask *arrayTask = NULL;
#define LOGD(x, ...) printf(x, ##__VA_ARGS__)
#define LOGI(x, ...) printf(x, ##__VA_ARGS__)
static stack
void *co_accept(void *p)
{
co_enable_hook_sys();
int fd = socket(AF_INET,SOCK_STREAM,0);
{
struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port=htons(90); ///监听端口
local.sin_addr.s_addr=inet_addr("127.0.0.1");
::bind(fd, (struct sockaddr*)&local,sizeof local);
::listen(fd, 1024);
SetNonBlock(fd);
}
static struct sockaddr_in g_addr;
socklen_t g_len=0;
while(1)
{
if(freeco.empty())
{
poll(0,0,1);
continue;
}
{ //判断是否有新连接
struct pollfd pf = { 0 };
pf.fd = fd;
pf.events = (POLLIN|POLLERR|POLLHUP);
if(0 == co_poll( co_get_epoll_ct(),&pf,1,3000))
continue;
}
memset(&g_addr,0,sizeof(g_addr));
//唯独accept没有被hook,所以这里的accept_fd要设成NONBLOCK. 本函数开头已设
int newfd = accept(fd, (struct sockaddr *)&g_addr, &g_len);
if( newfd < 0 )
{
continue;
}
if( freeco.empty() )
{
close( newfd ); //协程不够用。。关连接
LOGD("tcp proc co not enough");
continue;
}
SetNonBlock( newfd );
STask *co = freeco.top();
co->fd = newfd;
freeco.pop();
co_resume( co->pCo);
}
LOGD("co_accept end...\n");
}
void * deal_tcp_routine(void *arg)
{
co_enable_hook_sys();
STask *co = (STask *)arg;
int sbuflen = 256;//只能是栈上变量..
char buf[ sbuflen ];
for(;;)
{
if(co->fd <= 0)
{
freeco.push( co );
co_yield_ct();
continue;
}
int fd = co->fd;
sockaddr_in addr;
if(fd <= 0) assert(0);
co->fd = -1;
for(;;)
{
struct pollfd pf = { 0 };
pf.fd = fd;
pf.events = (POLLIN|POLLERR|POLLHUP);
int raiseCount = co_poll(co_get_epoll_ct(),&pf,1,1000);
if(raiseCount == 0) continue; //epoll的socket事件没被激活, 继续epoll
int ret = read( fd,buf, sizeof(buf));
if(ret <= 0)
{
close(fd);
break; //会回到外层循环, 然后co->u.fd已被设为-1, 进入队列休眠
}
send(fd, buf, ret, 0);
}
}
return 0;
}
void run()
{
arrayTask = new STask[1 + cocount];
co_create(&arrayTask[0].pCo, NULL, co_accept, &arrayTask[0]);
co_resume(arrayTask[0].pCo);
for(int i = 1; i < 1 + cocount; i++)
{
co_create(&arrayTask[i].pCo, NULL, deal_tcp_routine, &arrayTask[i]);
co_resume(arrayTask[i].pCo);
}
co_eventloop(co_get_epoll_ct(), 0, 0);
LOGD("end of run...\n");
}
void SignalHandler(int nSigno)
{
switch(nSigno)
{
case SIGPIPE:
LOGI("sigpipe occurred...\n");
signal(SIGPIPE , &SignalHandler);
break;
}
}
int main(int, char *[])
{
signal(SIGPIPE , &SignalHandler);
run();
return 0;
}