1. 程式人生 > >[c語言 ] 用libev 寫個echo伺服器

[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 只有一個檔案..呵呵

#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;

// 建立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;
}



// 初始化,這裡監聽了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事件 的回撥塊
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結構
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");

//開始監聽讀事件了,有客戶端資訊就會被監聽到
ev_io_init(w_client, read_cb, client_sd, EV_READ);
ev_io_start(loop, w_client);
}

//read 資料事件的回撥快
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就可以,同時記得釋放客戶端的結構體!
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);
}

編譯後,執行. 然後開啟teminal ,   telnet 127.0.0.1 9999  就可以傳送資訊了.


入手c的網路程式設計,將來,對比下erlang的底層網路通訊是怎麼弄的

~~by dp


相關推薦

[c語言 ] libev echo伺服器

   放假了.同學都回家了,我是更情願留久點在學校,一來學校安靜,二來免得火車太擠.  這臨走前的幾天,放下了erlang,寫了一下c. 其實只是對比下erlang 寫socket伺服器,和c寫socket伺服器的異同. 說一下libev: Libev是一個event l

C語言入門常的三程式碼

今天我們要看的是C語言常寫的三個程式碼。 列印100~200之間的素數 常用的方法是試除法,解釋一下什麼是試除法。 “試除”顧名思義就是不斷的嘗試能否整除,比如要判斷一個自然數x是否是質數,就不斷用這個數x去除以小於x且大於1的自然數,只要有一個能整除,則x就是合數,否則x是質數

C語言,有N硬幣面值為a[1]...a[N],給一個非負數m,這些硬幣湊成m,求有多少種方法?

#include <stdio.h> #include <memory.h> #define N 1000 #define M 100000 int a[N]; int DP[M]; int dpItUnlimited(int m, i

c語言 getchar函式讀入兩字元給c1 c2 putchar和printf輸出 思考問題

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

C語言 選擇法對10整數排

#include<stdio.h> int main() {int a[10],i,j,t; for(i=0;i<10;i++) scanf("%d",&a[i]); for(i=0;i<10;i++) for(j=i+1;j<10;j++)

c語言 指標交換兩整數附記憶體圖

// Pointer.cpp : 定義控制檯應用程式的入口點。 // !!!!!!VS2015中編輯的 #include “stdafx.h” void swap1(int *x, int *y); void swap2(int *x, int *y); int main() { int

記錄我C語言解的第一方程~

就是很簡單的ax^2+bx+c=0 #include<stdio.h> #include<math.h> void fun(float a, float b, float c) { float x1,x2,d; d=b*b-4*a*

ACMNO.25 C語言-間隔輸出 一函式,輸入一個四位數字,要求輸出這四數字字元,但每兩數字間空格。如輸入1990,應輸出"1 9 9 0"。 輸入 一個四位數 輸出 增加空格輸出

題目描述 寫一函式,輸入一個四位數字,要求輸出這四個數字字元,但每兩個數字間空格。如輸入1990,應輸出"1 9 9 0"。 輸入 一個四位數 輸出 增加空格輸出 樣例輸入 1990 樣例輸出 1 9 9 0 來源/分類 C語言

c語言】將兩字串連線起來,不要strcat函式

#include <stdio.h> int main() { char s1[80],s2[40]; int i=0,j=0; printf("input string1:"); scanf("%s",s1); printf("input strin

c語言連結串列的一個簡單的學生管理系統

在大學由於在學完c語言之後老師佈置了一個寫學生管理系統的課設我寫了一個簡單的學生管理 系統,話不多說,直接上原始碼。 #include<stdio.h> #include<stdlib.h> #include<string.h> char

[c語言]遞迴和非遞迴求第n斐波那契數

程式碼 //1.1遞迴求第n個斐波那契數 #include<stdio.h> int fib(int n) { if(n<=2) return 1; else return fib(n-1)+fib(n-2); } int main

C語言實現判斷兩陣列中是否有相同的元素,有就輸出“有”,沒有則輸出“沒有”

建立兩個陣列,讓第一個陣列中的元素依次與第二個陣列中的元素比較(想讓第一個陣列中的第一個元素與第二個陣列中每個元素比較),若找到相同的,則計數並且計數停止,若計數不為零,則有相同元素,否則沒有。test.c#include<stdio.h> int main()

C語言-輸入任意多數字,數字間空格隔開,然後將數字求和。

C語言練習,看到一個題目:輸入任意多個數字,數字間用空格隔開,然後將數字求和。 苦於不會用連結串列來做一個動態陣列,所以用了一個土辦法,先定義一個“足夠大”的陣列,然後將使用者輸入的數字填入陣列,同時用變數記錄填入的個數,用於後面for迴圈的迴圈次數限制。最後用for迴圈求

C語言指標互換兩數字

#include<stdio.h>void change(int *p , int *q){    int t;     t=*p;    *p=*q;    *q=t;}int main(void){    int a=3;    int b=5;    cha

C語言指標實現兩陣列值互換

C語言用指標實現兩陣列的值互換 #include <stdio.h> #define N 10 void ReadData(int a[], int n); void PrintDa

C語言合並兩集合(L,L1) 將L1中不在L中的元素插入到L線性表中

時間復雜度 itl main 所有 bsp 插入 復雜 i++ ins void main(){ Sqlist L,L1; InitList(&L); InitList(&L1); ListInsert(&L, 1, 2); ListIns

python隨機驗證碼

range emp pytho [] and random code port rand 隨機驗證碼 import random li = [] for i in range(8): r = random.randrange(0,5) print(r)

C語言:解決多C檔案包含同一標頭檔案引起的檔案重複包含問題

解決多個C檔案包含同一標頭檔案引起的檔案重複包含問題,並給出全域性變數如何定義和宣告的方法. 解決方法: 1. 定義公共檔案: global.c 和global.h 其中, global.c檔案中: #include "global.h" //定義全域性變數 int g

Python 一個TCP 伺服器和TCP代理

TCP伺服器 import socket import threading bind_ip="0.0.0.0" bind_port=9999 server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind((bind_i

c 語言 函式遞迴來實現求 k 的 n 次方

       如果求取k的n次方,既可以用普通的方法實現,也可以用函式的遞迴來實現。        函式的遞迴即是自己呼叫自己的函式應用形式,即在main函式下定義一個函式,然後在這個函式內自己為了實現某個目的,函式