socket客户端服务器c语言,纯C语言版本的socket.io服务器端实现

前言

哈,这又是一个socket.io服务端实现,本意是,拿C练练手,加强对C和linux系统的理解,写着写着,就写成了一个socket.io服务器端实现了。以为半成品,那就正式托管在github站点上吧,以便记录一下,可让大家批评与指正,加强内功的修炼等。

以下部分文字,偷懒,摘录自项目的README.md文件

说明

这是一个纯C语言版本的socket.io服务器端实现,目前仅支持linux系统,严重依赖libev and glib等基础库。

在运行socket.io_server之前,需要安装以下依赖:

sudo apt-get install uuid-dev

sudo apt-get install libglib2.0-dev

如何运行

编写实现代码(eg:chatroom.c),需要包含头文件 endpoint_impl.h

把实现代码(eg:chatroom.c)放入examples目录

编写对应的html文件,放入static目录

编辑Makefile文件

终端下运行make命令

然后敲入 ./socket.io_server 接口运行

打开浏览器即可访问 (eg:http://localhost:8000/chatroom.html)

API说明

对外的API,可以在头文件 endpoint_impl.h 看到其定义,其继承了另外一个公用的头文件 endpoint.h, 其完整定义为:

#include 

#include 

#include 

typedefstruct{

char*message_type;

char*message_id;

char*endpoint;

char*message_data;

char*ori_data;

} message_fields;

typedefstruct{

char*endpoint;

void(*on_init)(constchar*endpoint);

void(*on_connect)(constchar*sessionid);

void(*on_message)(constchar*sessionid,constmessage_fields *msg_fields);

void(*on_json_message)(constchar*sessionid,constmessage_fields *msg_fields);

void(*on_event)(constchar*sessionid,constmessage_fields *msg_fields);

void(*on_other)(constchar*sessionid,constmessage_fields *msg_fields);

void(*on_disconnect)(constchar*sessionid,constmessage_fields *msg_fields);

void(*on_destroy)(constchar*endpoint);

} endpoint_implement;

externvoidsend_msg(char*sessionid,char*message);

externvoidbroadcast_clients(char*except_sessionid,char*message);

staticvoidon_init(constchar*endpoint);

staticvoidon_connect(constchar*sessionid);

staticvoidon_message(constchar*sessionid,constmessage_fields *msg_fields) {

printf("on_message recevie ori msg is %s\n", msg_fields->ori_data);

}

staticvoidon_json_message(constchar*sessionid,constmessage_fields *msg_fields) {

printf("on_json_message recevie ori msg is %s\n", msg_fields->ori_data);

}

staticvoidon_other(constchar*sessionid,constmessage_fields *msg_fields) {

printf("on_other recevie ori msg is %s\n", msg_fields->ori_data);

}

staticvoidon_event(constchar*sessionid,constmessage_fields *msg_fields);

staticvoidon_disconnect(constchar*sessionid,constmessage_fields *msg_fields);

staticvoidon_destroy(constchar*endpoint);

staticendpoint_implement *init_default_endpoint_implement(char*endpoint_name) {

endpoint_implement *impl_point = (endpoint_implement *)malloc(sizeof(endpoint_implement));

impl_point->endpoint = strdup(endpoint_name);

impl_point->on_init = on_init;

impl_point->on_connect = on_connect;

impl_point->on_message = on_message;

impl_point->on_json_message = on_json_message;

impl_point->on_event = on_event;

impl_point->on_other = on_other;

impl_point->on_disconnect = on_disconnect;

impl_point->on_destroy = on_destroy;

returnimpl_point;

}

在example目录中,你可以看到聊天室演示chatroom 和在线白板示范whiteboard .

#include 

#include 

#include 

#include 

#include "../endpoint_impl.h"

typedefstruct{

char*event_name;

char*event_args;

} event_message;

staticchar*event_message_reg ="{\"name\":\"(.*?)\",\"args\":\\[([^\\]]*?)\\]}";

staticgchar *get_match_result(GMatchInfo *match_info, gint index) {

gchar *match = g_match_info_fetch(match_info, index);

gchar *result = g_strdup(match);

g_free(match);

returnresult;

}

staticvoid*message_2_struct(gchar *post_string, event_message *event_msg) {

GError *error = NULL;

GRegex *regex;

GMatchInfo *match_info;

regex = g_regex_new(event_message_reg, 0, 0, &error );

g_regex_match( regex, post_string, 0, &match_info );

if(g_match_info_matches(match_info)) {

event_msg->event_name = get_match_result(match_info, 1);

event_msg->event_args = get_match_result(match_info, 2);

}else{

event_msg = NULL;

}

g_match_info_free( match_info );

g_regex_unref( regex );

returnevent_msg;

}

staticGHashTable *hashtable;

staticvoidhashtable_init(void) {

hashtable = g_hash_table_new(g_str_hash, g_str_equal);

}

staticvoidhashtable_add(constchar*key,void*value) {

if(key) {

g_hash_table_insert(hashtable, g_strdup(key), value);

}

}

staticgboolean hashtable_remove(constchar*key) {

if(key)

returng_hash_table_remove(hashtable, key);

return0;

}

staticvoid*hashtable_lookup(constchar*key) {

if(key == NULL)

returnNULL;

returng_hash_table_lookup(hashtable, key);

}

/*static gint hashtable_size(void) {

return g_hash_table_size(hashtable);

}*/

staticvoidhashtable_destroy(void) {

g_hash_table_destroy(hashtable);

}

/**

** use the struct to warpper the demo implment

**/

staticchar*endpoint_name;

staticvoidon_init(constchar*endpoint) {

hashtable_init();

printf("%s has been inited now\n", endpoint);

endpoint_name = g_strdup(endpoint);

}

staticvoidon_connect(constchar*sessionid) {

charmessages[strlen(sessionid) + 50];

sprintf(messages,"5::%s:{\"name\":\"clientId\",\"args\":[{\"id\":\"%s\"}]}", endpoint_name, sessionid);

send_msg(sessionid, messages);

}

staticvoidsend_it(char*session_id,char*messaage) {

send_msg(session_id, messaage);

}

staticvoidfree_event_msg(event_message *event_msg) {

free(event_msg->event_name);

free(event_msg->event_args);

}

staticvoidon_event(constchar*sessionid,constmessage_fields *msg_fields) {

event_message event_msg;

if(!message_2_struct(msg_fields->message_data, &event_msg)) {

fprintf(stderr,"%s Parse Message Error !\n", msg_fields->ori_data);

return;

}

if(!strcmp(event_msg.event_name,"roomNotice")) {

/*5::/whiteboard:{"name":"roomNotice","args":[{"room":"myRoom"}]}*/

chartarget_room_id[strlen(event_msg.event_args) - 10];// = event_msg.event_args + 9;

strncpy(target_room_id, event_msg.event_args + 9, strlen(event_msg.event_args) - 11);

GPtrArray *list = (GPtrArray *)hashtable_lookup(target_room_id);

if(list == NULL) {

list = g_ptr_array_new();

hashtable_add(target_room_id, list);

}

g_ptr_array_add(list, g_strdup(sessionid));

introom_count = list->len;

charmessages[strlen(sessionid) + 200];

sprintf(messages,"5::%s:{\"name\":\"roomCount\",\"args\":[{\"room\":\"%s\",\"num\":%d}]}", endpoint_name, target_room_id, room_count);

hashtable_add(g_strdup(sessionid), g_strdup(target_room_id));

g_ptr_array_foreach(list, (GFunc)send_it, messages);

free_event_msg(&event_msg);

return;

}

charmessages[strlen(msg_fields->ori_data) + 200];

sprintf(messages,"5::%s:{\"name\":\"%s\",\"args\":[%s]}", endpoint_name, event_msg.event_name, event_msg.event_args);

free_event_msg(&event_msg);

char*target_room_id = (char*)hashtable_lookup(sessionid);

GPtrArray *list = (GPtrArray *)hashtable_lookup(target_room_id);

if(list == NULL){

return;

}

inti;

for(i = 0; i len; i++) {

char*session_id = g_ptr_array_index(list, i);

if(strcmp(session_id, sessionid) == 0)

continue;

send_msg(session_id, messages);

}

}

staticvoidon_disconnect(constchar*sessionid,constmessage_fields *msg_fields) {

char*room_id = (char*)hashtable_lookup(sessionid);

if(room_id == NULL) {

fprintf(stderr,"the room_id is NULL\n");

return;

}

charnotice_msg[strlen(endpoint_name) + strlen(room_id) + 70];

GPtrArray *list = (GPtrArray *)hashtable_lookup(room_id);

sprintf(notice_msg,"5::%s:{\"name\":\"roomCount\",\"args\":[{\"room\":\"%s\",\"num\":%d}]}", endpoint_name, room_id, list->len - 1);

inti, remove_index;

for(i = 0; i len; i++) {

char*session_id = g_ptr_array_index(list, i);

if(strcmp(session_id, sessionid) == 0) {

remove_index = i;

continue;

}

send_msg(session_id, notice_msg);

}

g_ptr_array_remove_index(list, remove_index);

hashtable_remove(sessionid);

free(room_id);

}

staticvoidon_destroy(constchar*endpoint) {

printf("%s has been destroy now\n", endpoint);

hashtable_destroy();

free(endpoint_name);

}

externendpoint_implement *init_whiteboard_endpoint_implement(char*endpoint_name) {

returninit_default_endpoint_implement(endpoint_name);

}

因为C语言中没有散列表,只好借助于成熟的glib库实现。

其它

项目不太成熟,期待大家的参与,您的建议、批评和指正,都是一种激励,再次表示感谢。

【编辑推荐】

【责任编辑:小林 TEL:(010)68476606】

点赞 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值