[c语言 ] 用libev 写个echo服务器
生活随笔
收集整理的這篇文章主要介紹了
[c语言 ] 用libev 写个echo服务器
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
放假了.同學(xué)都回家了,我是更情愿留久點(diǎn)在學(xué)校,一來學(xué)校安靜,二來免得火車太擠.? 這臨走前的幾天,放下了erlang,寫了一下c. 其實(shí)只是對比下erlang 寫socket服務(wù)器,和c寫socket服務(wù)器的異同.
#include?<stdio.h>?? #include?<netinet/in.h>?? #include?<ev.h>?? ?? #define?PORT?9999?? #define?BUFFER_SIZE?1024?? ?? ?? void?accept_cb(struct?ev_loop?*loop,?struct?ev_io?*watcher,?int?revents);?? ?? ?? void?read_cb(struct?ev_loop?*loop,?struct?ev_io?*watcher,?int?revents);?? ?? int?main()?? {?? struct?ev_loop?*loop?=?ev_default_loop(0);?? int?sd;?? struct?sockaddr_in?addr;?? int?addr_len?=?sizeof(addr);?? struct?ev_io?socket_accept;?? ?? //?創(chuàng)建socket的寫法,這里簡單處理,用INADDR_ANY?,匹配任何客戶端請求.這里寫法都一樣,沒什么特別的,直接copy都可以用?? if(?(sd?=?socket(PF_INET,?SOCK_STREAM,?0))?<?0?)?? {?? ??printf("socket?error");?? ??return?-1;?? }?? bzero(&addr,?sizeof(addr));?? addr.sin_family?=?AF_INET;?? addr.sin_port?=?htons(PORT);?? addr.sin_addr.s_addr?=?INADDR_ANY;?? if?(bind(sd,?(struct?sockaddr*)?&addr,?sizeof(addr))?!=?0)?? {?? ??printf("bind?error");?? }?? if?(listen(sd,?2)?<?0)?? {?? ??printf("listen?error");?? ??return?-1;?? }?? ?? ?? ?? //?初始化,這里監(jiān)聽了io事件,寫法參考官方文檔的?? ev_io_init(&socket_accept,?accept_cb,?sd,?EV_READ);?? ev_io_start(loop,?&socket_accept);?? ?? ?? while?(1)?? {?? ??ev_loop(loop,?0);?? }?? ?? return?0;?? }?? ?? ?? ?? //accept事件?的回調(diào)塊?? void?accept_cb(struct?ev_loop?*loop,?struct?ev_io?*watcher,?int?revents)?? {?? struct?sockaddr_in?client_addr;?? socklen_t?client_len?=?sizeof(client_addr);?? int?client_sd;?? ?? //分派客戶端的ev?io結(jié)構(gòu)?? struct?ev_io?*w_client?=?(struct?ev_io*)?malloc?(sizeof(struct?ev_io));?? ?? //libev的錯誤處理?? if(EV_ERROR?&?revents)?? {?? ??printf("error?event?in?accept");?? ??return;?? }?? ?? //accept,普通寫法?? client_sd?=?accept(watcher->fd,?(struct?sockaddr?*)&client_addr,?&client_len);?? if?(client_sd?<?0)?? {?? ??printf("accept?error");?? ??return;?? }?? ?? printf("someone?connected.\n");?? ?? //開始監(jiān)聽讀事件了,有客戶端信息就會被監(jiān)聽到?? ev_io_init(w_client,?read_cb,?client_sd,?EV_READ);?? ev_io_start(loop,?w_client);?? }?? ?? //read?數(shù)據(jù)事件的回調(diào)快?? void?read_cb(struct?ev_loop?*loop,?struct?ev_io?*watcher,?int?revents){?? char?buffer[BUFFER_SIZE];?? ssize_t?read;?? ?? if(EV_ERROR?&?revents)?? {?? ??printf("error?event?in?read");?? ??return;?? }?? ?? //recv普通socket寫法?? read?=?recv(watcher->fd,?buffer,?BUFFER_SIZE,?0);?? ?? if(read?<?0)?? {?? ??printf("read?error");?? ??return;?? }?? ?? //斷開鏈接的處理,停掉evnet就可以,同時記得釋放客戶端的結(jié)構(gòu)體!?? if(read?==?0)?? {?? ??printf("someone?disconnected.\n");?? ??ev_io_stop(loop,watcher);?? ??free(watcher);?? ??return;?? }?? else?? {?? ??printf("get?the?message:%s\n",buffer);?? }?? ?? //原信息返回,也可以自己寫信息,都一樣.最后記得置零?? send(watcher->fd,?buffer,?read,?0);?? bzero(buffer,?read);?? }??
編譯后,運(yùn)行. 然后打開teminal ,?? telnet 127.0.0.1 9999? 就可以發(fā)送信息了.
說一下libev:? 點(diǎn)擊打開鏈接
Libev是一個event loop:向libev注冊感興趣的events,比如Socket可讀事件,libev會對所注冊的事件的源進(jìn)行管理,并在事件發(fā)生時觸發(fā)相應(yīng)的程序。 ? 對比另外一個更加出名的libevent,這個更加先進(jìn). 小巧輕量.? 源碼解讀就不獻(xiàn)丑了,一堆堆宏.我功力不夠去深層切入libev.官網(wǎng)有文檔,弄成pdf了,可以下載: http://d.yun.io/Y9ziuo
說一下環(huán)境: ubuntu 11.10 ,gcc4.4.6 ,libev 4.11,? code:block(vim,emacs黨...莫要黑,我用CB好久了,莫要離間!!!)
官方文檔是有個鍵盤輸入的demo,網(wǎng)上也有幾個用libev寫echo sever的,感覺都寫得很不錯,很全面.? 我還是參考他們寫個簡單,簡陋的試一下吧.
main.c 只有一個文件..呵呵
[cpp] view plain copy
編譯后,運(yùn)行. 然后打開teminal ,?? telnet 127.0.0.1 9999? 就可以發(fā)送信息了.
入手c的網(wǎng)絡(luò)編程,將來,對比下erlang的底層網(wǎng)絡(luò)通訊是怎么弄的
~~by dp
總結(jié)
以上是生活随笔為你收集整理的[c语言 ] 用libev 写个echo服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux系统文件I/O编程(一)---
- 下一篇: libevent之Reactor模式详解