网络通信引擎--C++ 与 lua

来源:互联网 发布:京东 省市区数据库 编辑:程序博客网 时间:2024/06/05 03:28

最近想做一个网信引擎 想要C++结合lua 来写 ,C++层用epoll  ,lua 层来进行逻辑处理 ,后期想加上protobuf .

可能引擎刚开始还是很初级,本人想不断将期完善 ,满足其本的功能。

1. 写一个lua解释器程序, 比如 test test.lua  

test 是一个可执行文件,与lua 文件进行交互,test接受数据,交给lua 代码来进行逻辑处理,lua 将处理结果返回给C++层,test将处理后的数据发送给相应的连接。


2.C++ 这一块 用epoll ,不断地接受客户端的连接与数据 ,刚开始直接用单线程,后面可能会用线程池,任务队列,来保证稳定性。

=========> 后来发现用单线程不行,在收到epollIN 消息时,来解析数据包,或者做其他操作,可能耗时较长,从而形成阻塞的情况,因为ET模式,有阻塞的情况,后面的连接就没法连接上,而没丢弃。找了好久,终于发现用线程池,信号量、加锁可以解决这种情况。在后面会贴出代码


struct task{  int fd; //需要读写的文件描述符  struct task *next; //下一个任务};

//线程的任务函数void * readtask(void *args);pthread_mutex_t mutex;pthread_cond_t cond1;//目标条件变量struct task *readhead=NULL,*readtail=NULL,*writehead=NULL;
pthread_t tid1,tid2;   pthread_mutex_init(&mutex,NULL);    pthread_cond_init(&cond1,NULL);    //初始化用于读线程池的线程    pthread_create(&tid1,NULL,readtask,NULL);    pthread_create(&tid2,NULL,readtask,NULL);

if (events[i].events & EPOLLIN){    if ( sockfd < 0) continue;      new_task=new task();              new_task->fd=sockfd;              new_task->next=NULL;//添加新的读任务                pthread_mutex_lock(&mutex);if(readhead==NULL)                {                      readhead=new_task;                      readtail=new_task;                }                 else                {                      readtail->next=new_task;                      readtail=new_task;                }  //唤醒所有等待cond1条件的线程                 pthread_cond_broadcast(&cond1);                 pthread_mutex_unlock(&mutex); 
}

static int count111 = 0;void * readtask(void *args){    int fd=-1;   unsigned int n;   //用于把读出来的数据传递出去   while(1){                pthread_mutex_lock(&mutex);        //等待到任务队列不为空        while(readhead==NULL) // 当连接的链表为空时             pthread_cond_wait(&cond1,&mutex); // 等待条件变量                fd=readhead->fd;        //从任务队列取出一个读任务        struct task *tmp=readhead;        readhead = readhead->next;        delete tmp;        pthread_mutex_unlock(&mutex);        data = new user_data();        data->fd=fd;        char recvBuf[1024] = {0};         int ret = 999;        int rs = 1;        while(rs)        {            ret = recv(fd,recvBuf,1024,0);// 接受客户端消息cout <<"the data recv ret = " << ret <<endl; if (ret > 0 ) {recvBuf[ret] = '\0';string data = recvBuf;                  //数据的解析demo::People p;  p.ParseFromString(data);  cout << "People: " << endl;  cout << "Name: " << p.name() << endl;  cout << "ID: " << p.id() << endl;  cout << "Email: " << p.email() << endl;     }            if(ret < 0)            {                //由于是非阻塞的模式,所以当errno为EAGAIN时,表示当前缓冲区已无数据可//读在这里就当作是该次事件已处理过。                if(errno == EAGAIN)                {                    printf("EAGAIN\n");                    break;                }                else{                    printf("recv error!\n");                            close(fd);                    break;                }            }            else if(ret == 0)            {                // 这里表示对端的socket已正常关闭.                 rs = 0;            }            if(ret == sizeof(recvBuf))                rs = 1; // 需要再次读取            else                rs = 0;        }        if(ret>0){  //返回数据             char buf[1000] = {0};            sprintf(buf,"HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\n%s","Hello world!\n");            send(fd,buf,strlen(buf),0);            close(fd);       }   }}

http://blog.chinaunix.net/uid-1849361-id-2825417.html

http://blog.chinaunix.net/uid-311680-id-2439722.html


3. protobuf 数据的解析 是放在C++ 这层还是在 lua 层 着实让人有点为难 ,暂时没想到的办法,后期找到了会更新到csdn

 

-- 设置服务器端口与ip

function setServerForEpoll(port,ip)


end

对应的C++ 代码 

lua_State* L;const char * ip = NULL ;  ---  作为全局变量 int port = 0;  static int setServerForEpoll( lua_State *L ){int n=lua_gettop(L);cout << "====>" <<n <<endl;if (lua_isstring(L,1)){     ip = lua_tostring(L,1); cout << ip <<endl;}if(lua_isnumber(L,2)){port = lua_tonumber(L,2);cout << port <<endl;}return 0; --- 返回数为0}

-- 对接受的消息做处理
function onReadData(data,sockfd,cmd)

     print("=================>",data.Name,data.ID,sockfd,cmd);
     return 100;

end

C++ 代码如下

        lua_getglobal(L,"onReadData");//压入函数名  lua_newtable(L);  //压入一个table {Name: ,ID: ,Email: }                lua_pushstring(L, "Name");                  lua_pushstring(L, p.name().c_str());                  lua_settable(L, -3);                  lua_pushstring(L, "ID");                  lua_pushnumber(L, 123 );                lua_settable(L, -3);  lua_pushstring(L, "Email:");                  lua_pushstring(L, p.email().c_str());                  lua_settable(L, -3);                 lua_pushnumber(L,sockfd);int cmd = 1001;                lua_pushnumber(L,cmd);                lua_pcall(L,3,1,0);                  int num =(int)lua_tonumber(L,-1);//处理返回值                  cout << num <<endl;                lua_pop(L,1); 
如是是返回一个table 代码下次会贴出来


--- 消息单发
function sendData(sockfd, data ,cmd)
{


}


--- 消息群发
function sendToAll(data,cmd)
{


}


--- 得到当前连接的句柄
function getSockfd(cmd)
{


}
0 0
原创粉丝点击