网络通信引擎--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
- 网络通信引擎--C++ 与 lua
- Lua与C通信——Lua API(一)
- C++与Lua通信
- 【Lua】Lua与C交互
- 网络编程-实验2-C与C通信
- LUA与C++通信(一)
- lua与C++互相通信
- C#:网络通信(TCP)
- lua与c互调--c调用lua
- lua与c互调--lua调用c
- Lua 与C交互
- Lua 与 C 交互
- Lua与C混编
- lua与C/C++
- Lua 与C交互
- Lua 与C交互
- Lua 与C交互
- Lua 与 C 交互
- c++中比较三个数的大小
- Qt中使用QSqlDatabase::removeDatabase()的正确方法
- 第十一章 字符串和字符串函数(字符串标准输入输出库函数)总结 140527
- Gabor的OpenCV代码
- tomcat优化-有改protocol 和 缓存 集群方案 转载自http://passover.blog.51cto.com/2431658/732629
- 网络通信引擎--C++ 与 lua
- asp.net中后台c#数组与前台js数组交互
- 安卓开发的心得体会
- struct1 页面跳转配置Demo
- struts2 Result type
- 病毒样本分析小结
- AIX中常用的SMIT 的使用
- ZOJ-2545
- 设计模式精粹