免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 4127 | 回复: 21
打印 上一主题 下一主题

[C] 求教libevent用法 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-03-26 15:58 |只看该作者 |倒序浏览
服务端逻辑:
              使用本地sock(绑定文件的,STREAM), 接收字符串, 返回字符串, 关闭连接

客户端逻辑:
              主动连接服务端,发送字符串,接收字符串,关闭连接, 重新连接服务端,无限循环

问题:
       accept只能触发一次。 就是当客户端第一次建立连接时,accept事件和read事件都能正常返回。 当客户端第二次连接时,accept事件就不会返回了

问:
     accept事件需要每次用完,再重新添加进base吗? 怎样重新添加呢? 先event_free或者event_del,然后再add吗?

服务端
  1. #include "task.h"

  2. struct event_base *TaskReadEvBase;
  3. void TaskReadEvFun(int sd, short event, void *arg);

  4. void *ReadTaskEvThead(void *arg){
  5.         TaskListenPort *ListenPort=(TaskListenPort *)arg;
  6.         struct event *TaskReadEv=NULL;

  7.         TaskReadEvBase=event_base_new();
  8.         TaskReadEv=event_new(TaskReadEvBase, ListenPort->sd, EV_READ|EV_PERSIST, TaskAcceptEvFun, (void *)TaskReadEv);
  9.         if(TaskReadEv==NULL){
  10.                 perror("event_new");
  11.                 pthread_exit(NULL);
  12.         }       
  13.         event_add(TaskReadEv, NULL);
  14.         event_base_dispatch(TaskReadEvBase);
  15.         printf("event_base_dispatch over");
  16.         pthread_exit(NULL);
  17. }

  18. void TaskReadEvFun(int sd, short event, void *arg){
  19.         int len=0;
  20.         char buf[256];
  21.         struct event *TaskReadEv=(struct event *)arg;
  22.        

  23.         printf("==================\n");
  24.         printf("sd=%d\n", sd);
  25.         bzero(buf, 256);
  26.         len=recv(sd, buf, 256, 0);
  27.         printf("recvbuf=%s\n", buf);
  28.         write(sd, "over\n", 5);
  29.         perror("write");
  30.         printf("sd=%d\n", event_get_fd(TaskReadEv));
  31.         close(event_get_fd(TaskReadEv));
  32.         event_free(TaskReadEv);
  33.         return;
  34. }

  35. void TaskAcceptEvFun(int sd, short event, void *arg){
  36.         int newsd=0;
  37.         struct sockaddr_un addr;
  38.         socklen_t isinsize=0;
  39.         struct event *TaskReadEv=NULL;
  40.         struct event *TaskAcceptEv=(struct event *)arg;
  41.        
  42.         printf("accept event\n");
  43.         newsd = accept(sd, (struct sockaddr *)&addr, &isinsize);
  44.         if(newsd==-1){
  45.                 printf("TaskAcceptEvFun error\n");
  46.                 perror("accept");
  47.                 return;
  48.         }
  49.         evutil_make_socket_nonblocking(newsd);
  50.         TaskReadEv=event_new(TaskReadEvBase, newsd, EV_READ|EV_PERSIST, TaskReadEvFun, (void *)TaskReadEv);
  51.         if(TaskReadEv==NULL){
  52.                 perror("event_new error\n");
  53.                 return;
  54.         }
  55.         event_add(TaskReadEv, NULL);
  56.         //event_add(TaskAcceptEv, NULL);
  57. }

  58. int init_task_listen(TaskListenPort *port){
  59.         int sd=0, ret=0;
  60.         struct sockaddr_un addr;

  61.         sd=socket(PF_UNIX, SOCK_STREAM, 0);
  62.         if(sd==-1){
  63.                 perror("socket");
  64.                 remove(port->portfile);
  65.                 return ERR;
  66.         }
  67.        
  68.         evutil_make_socket_nonblocking(sd);
  69.        
  70.         addr.sun_family=AF_UNIX;
  71.         strncpy(addr.sun_path, port->portfile, sizeof(addr.sun_path)-1);
  72.         ret=bind(sd, (struct sockaddr *)&addr, sizeof(addr));
  73.         if(ret==-1){
  74.                 perror("bind");
  75.                 close(sd);
  76.                 return ERR;
  77.         }
  78.         ret=listen(sd, 256);
  79.         if(ret==-1){
  80.                 perror("listen");
  81.                 close(sd);
  82.                 return ERR;
  83.         }

  84.         return sd;
  85. }
复制代码
客户端
  1. //c_unix.c
  2. #include <stdio.h>
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <sys/un.h>
  6. #define UNIX_DOMAIN "/tmp/dataswsmb.port"
  7. int main(void)
  8. {
  9.         int connect_fd;
  10.         int ret;
  11.         char snd_buf[128];
  12.         int i;
  13.         while(1)
  14.         {
  15.                 static struct sockaddr_un srv_addr;
  16.                 connect_fd=socket(PF_UNIX,SOCK_STREAM,0);
  17.                 if(connect_fd<0)
  18.                 {
  19.                         perror("cannot create communication socket");
  20.                         return 1;
  21.                 }   
  22.                 srv_addr.sun_family=AF_UNIX;
  23.                 strcpy(srv_addr.sun_path,UNIX_DOMAIN);
  24.                 ret=connect(connect_fd,(struct sockaddr*)&srv_addr,sizeof(srv_addr));
  25.                 if(ret==-1)
  26.                 {
  27.                         perror("cannot connect to the server");
  28.                         close(connect_fd);
  29.                         return 1;
  30.                 }
  31.                 perror("connect");
  32.                 memset(snd_buf,0x00,128);
  33.                 strcpy(snd_buf,"message from client");

  34.                 ret = write(connect_fd,snd_buf,sizeof(snd_buf));
  35.                 if (ret <= 0)
  36.                 {
  37.                         perror("write");
  38.                 }
  39.                 perror("write");
  40.                 memset(snd_buf,0x00,128);
  41.                 ret = read(connect_fd,snd_buf,sizeof(snd_buf));
  42.                 if (ret <= 0)
  43.                 {
  44.                         perror("read");
  45.                 }
  46.                 perror("read");
  47.                 printf("server returned : %s\n", snd_buf);
  48.                 close(connect_fd);
  49.                 printf("=================================\n");
  50.         }
  51.         return 0;
  52. }
复制代码

论坛徽章:
7
天秤座
日期:2014-08-07 13:56:30丑牛
日期:2014-08-27 20:34:21双鱼座
日期:2014-08-27 22:02:21天秤座
日期:2014-08-30 10:39:11双鱼座
日期:2014-09-21 20:07:532015年亚洲杯之日本
日期:2015-02-06 14:00:282015亚冠之大阪钢巴
日期:2015-11-02 14:50:19
2 [报告]
发表于 2015-03-26 16:43 |只看该作者
event_new的时候应该已经指定了base了,触发一次以后libevent应该会把他从关注的列表里面去掉,如果还要关注这个事件就重新event_add就可以了,但是不管监听不监听,他都在你初始化分配的base中。不过我对PERSIST理解还不太够

论坛徽章:
0
3 [报告]
发表于 2015-03-26 17:08 |只看该作者
回复 2# MeRcy_PM


   
重新ADD也不行 我试了。

论坛徽章:
7
天秤座
日期:2014-08-07 13:56:30丑牛
日期:2014-08-27 20:34:21双鱼座
日期:2014-08-27 22:02:21天秤座
日期:2014-08-30 10:39:11双鱼座
日期:2014-09-21 20:07:532015年亚洲杯之日本
日期:2015-02-06 14:00:282015亚冠之大阪钢巴
日期:2015-11-02 14:50:19
4 [报告]
发表于 2015-03-26 17:15 |只看该作者
回复 3# 故哈
是不是原来的fd已经close了,accept另一个fd,event_assign一下试试?

   

论坛徽章:
0
5 [报告]
发表于 2015-03-26 17:20 |只看该作者
回复 4# MeRcy_PM


    我这个不是网络socket,是本地sock, PF_UNIX的。


用来accept的sd应该是没有关闭 通过netstat看 还是LISTENING状态

论坛徽章:
0
6 [报告]
发表于 2015-03-26 17:25 |只看该作者
回复 4# MeRcy_PM


    应该是我哪里用的不对 第一次用

论坛徽章:
7
天秤座
日期:2014-08-07 13:56:30丑牛
日期:2014-08-27 20:34:21双鱼座
日期:2014-08-27 22:02:21天秤座
日期:2014-08-30 10:39:11双鱼座
日期:2014-09-21 20:07:532015年亚洲杯之日本
日期:2015-02-06 14:00:282015亚冠之大阪钢巴
日期:2015-11-02 14:50:19
7 [报告]
发表于 2015-03-26 17:35 |只看该作者
回复 5# 故哈
不好意思,刚没细看代码。在Accept之后添加了一个TaskReadEvFun的事件,但是在TaskReadEvFun这里面没有事件添加吧,所以到最后base里面都是空的事件吧?

   

论坛徽章:
0
8 [报告]
发表于 2015-03-27 09:30 |只看该作者
回复 7# MeRcy_PM


    TaskReadEvFun里边是没有添加事件的。

     因为我在TaskAcceptEvFun里边调用accept的时候,每次新建的socket都重新加了read事件, 那我在TaskReadEvFun里边是不是不需要重新添加read事件了?

论坛徽章:
0
9 [报告]
发表于 2015-03-27 09:32 |只看该作者
回复 7# MeRcy_PM


    在read事件里边的socket其实每次recv之后就是要关闭的。

论坛徽章:
7
天秤座
日期:2014-08-07 13:56:30丑牛
日期:2014-08-27 20:34:21双鱼座
日期:2014-08-27 22:02:21天秤座
日期:2014-08-30 10:39:11双鱼座
日期:2014-09-21 20:07:532015年亚洲杯之日本
日期:2015-02-06 14:00:282015亚冠之大阪钢巴
日期:2015-11-02 14:50:19
10 [报告]
发表于 2015-03-27 09:39 |只看该作者
回复 8# 故哈
应该是添加accept事件吧。
我个人理解的服务器调用应该是listen->add_accept_ev->[accept->add_read_ev->deal_read_ev]->add_accept_ev]->[......

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP