[c语言 ] 用libev 写个echo服务器

放假了.同学都回家了,我是更情愿留久点在学校,一来学校安静,二来免得火车太挤.  这临走前的几天,放下了erlang,写了一下c. 其实只是对比下erlang 写socket服务器,和c写socket服务器的异同.


说一下libev:  点击打开链接
Libev是一个event loop:向libev注册感兴趣的events,比如Socket可读事件,libev会对所注册的事件的源进行管理,并在事件发生时触发相应的程序。   对比另外一个更加出名的libevent,这个更加先进. 小巧轻量.  源码解读就不献丑了,一堆堆宏.我功力不够去深层切入libev.官网有文档,弄成pdf了,可以下载: http://d.yun.io/Y9ziuo


说一下环境: ubuntu 11.10 ,gcc4.4.6 ,libev 4.11,  code:block(vim,emacs党...莫要黑,我用CB好久了,莫要离间!!!)

官方文档是有个键盘输入的demo,网上也有几个用libev写echo sever的,感觉都写得很不错,很全面.  我还是参考他们写个简单,简陋的试一下吧.

main.c 只有一个文件..呵呵

  1. #include <stdio.h>  
  2. #include <netinet/in.h>  
  3. #include <ev.h>  
  4.   
  5. #define PORT 9999  
  6. #define BUFFER_SIZE 1024  
  7.   
  8.   
  9. void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);  
  10.   
  11.   
  12. void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents);  
  13.   
  14. int main()  
  15. {  
  16. struct ev_loop *loop = ev_default_loop(0);  
  17. int sd;  
  18. struct sockaddr_in addr;  
  19. int addr_len = sizeof(addr);  
  20. struct ev_io socket_accept;  
  21.   
  22. // 创建socket的写法,这里简单处理,用INADDR_ANY ,匹配任何客户端请求.这里写法都一样,没什么特别的,直接copy都可以用  
  23. if( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )  
  24. {  
  25.   printf("socket error");  
  26.   return -1;  
  27. }  
  28. bzero(&addr, sizeof(addr));  
  29. addr.sin_family = AF_INET;  
  30. addr.sin_port = htons(PORT);  
  31. addr.sin_addr.s_addr = INADDR_ANY;  
  32. if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0)  
  33. {  
  34.   printf("bind error");  
  35. }  
  36. if (listen(sd, 2) < 0)  
  37. {  
  38.   printf("listen error");  
  39.   return -1;  
  40. }  
  41.   
  42.   
  43.   
  44. // 初始化,这里监听了io事件,写法参考官方文档的  
  45. ev_io_init(&socket_accept, accept_cb, sd, EV_READ);  
  46. ev_io_start(loop, &socket_accept);  
  47.   
  48.   
  49. while (1)  
  50. {  
  51.   ev_loop(loop, 0);  
  52. }  
  53.   
  54. return 0;  
  55. }  
  56.   
  57.   
  58.   
  59. //accept事件 的回调块  
  60. void accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)  
  61. {  
  62. struct sockaddr_in client_addr;  
  63. socklen_t client_len = sizeof(client_addr);  
  64. int client_sd;  
  65.   
  66. //分派客户端的ev io结构  
  67. struct ev_io *w_client = (struct ev_io*) malloc (sizeof(struct ev_io));  
  68.   
  69. //libev的错误处理  
  70. if(EV_ERROR & revents)  
  71. {  
  72.   printf("error event in accept");  
  73.   return;  
  74. }  
  75.   
  76. //accept,普通写法  
  77. client_sd = accept(watcher->fd, (struct sockaddr *)&client_addr, &client_len);  
  78. if (client_sd < 0)  
  79. {  
  80.   printf("accept error");  
  81.   return;  
  82. }  
  83.   
  84. printf("someone connected.\n");  
  85.   
  86. //开始监听读事件了,有客户端信息就会被监听到  
  87. ev_io_init(w_client, read_cb, client_sd, EV_READ);  
  88. ev_io_start(loop, w_client);  
  89. }  
  90.   
  91. //read 数据事件的回调快  
  92. void read_cb(struct ev_loop *loop, struct ev_io *watcher, int revents){  
  93. char buffer[BUFFER_SIZE];  
  94. ssize_t read;  
  95.   
  96. if(EV_ERROR & revents)  
  97. {  
  98.   printf("error event in read");  
  99.   return;  
  100. }  
  101.   
  102. //recv普通socket写法  
  103. read = recv(watcher->fd, buffer, BUFFER_SIZE, 0);  
  104.   
  105. if(read < 0)  
  106. {  
  107.   printf("read error");  
  108.   return;  
  109. }  
  110.   
  111. //断开链接的处理,停掉evnet就可以,同时记得释放客户端的结构体!  
  112. if(read == 0)  
  113. {  
  114.   printf("someone disconnected.\n");  
  115.   ev_io_stop(loop,watcher);  
  116.   free(watcher);  
  117.   return;  
  118. }  
  119. else  
  120. {  
  121.   printf("get the message:%s\n",buffer);  
  122. }  
  123.   
  124. //原信息返回,也可以自己写信息,都一样.最后记得置零  
  125. send(watcher->fd, buffer, read, 0);  
  126. bzero(buffer, read);  
  127. }  

编译后,运行. 然后打开teminal ,   telnet 127.0.0.1 9999  就可以发送信息了.



入手c的网络编程,将来,对比下erlang的底层网络通讯是怎么弄的


~~by dp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值