网页版群聊系统

在介绍网页版群聊系统之前,首先介绍一下此项目中用到的两个非常重要的工具:websocket协议和mongoose框架。

1、为什么要用websocket协议?

一个客户端发送消息之后,需要服务器主动把消息广播给所有的在线用户,但是http协议是惰性的,哪个客户端向服务器发起http请求,此客户端才会收到服务器的响应,这种机制不能满足群聊的要求,所以我们利用websocket协议来实现这个目的,websocket协议是全双工通信的,建立连接之后,客户端和服务器都可以主动接收或发送数据,下面我先介绍一下websocket协议:
websocket协议位于应用层,目标是在一个独立的持久连接上提供全双工双向通信,创建websocket协议之后,会有一个HTTP请求发给浏览器,服务器响应之后,建立的连接会利用HTTP协议将协议升级转换为websocket协议,随后再进行通信。也就是说websocket协议的建立需要先借助HTTP协议,在服务器返回101状态码之后,就可以进行websocket全双工通信了,此后就和HTTP没关系了。
协议如何升级:
HTTP请求的报头中的Upgrade设置为websocket可将协议升级为websocket协议。

2、为什么要用mongoose框架?

  • 底层采用了多路复用机制select
  • 运行占用很小的内存,使用时包含mongoose.c和mongoose.h到工程中即可

现在开始进入正题啦~~~
准备工作

  • 安装jsoncpp:https://github.com/open-source-parsers/jsoncpp/releases
	cd jsoncpp-1.8.3
	mkdir build
	cd build
	cmake ..
	make
	sudo make install
  • 安装mysql的C接口库C connector:https://dev.mysql.com/downloads/mysql/5.6.html#downl

项目简介

网页版群聊系统是基于websocket协议和mongoose框架实现的一个即时通信工具,利用session和cookie管理用户状态,用户注册账号并登录之后即可进行群聊。

应用技术

C++11 STL、HTTP协议、websocket协议、mongoose框架、session、cookie、mysql c connect、jsoncpp

项目演示

网页版群聊系统_第1张图片
网页版群聊系统_第2张图片
网页版群聊系统_第3张图片

部分代码实现

服务器初始化

        void InitServer()
        {
            signal(SIGPIPE, SIG_IGN);
            mg_mgr_init(&mgr,NULL);
            nc = mg_bind(&mgr, port.c_str(), EventHandler);
            //注册对登录页面的处理动作
            mg_register_http_endpoint(nc, "/LH", LoginHandler);
            mg_register_http_endpoint(nc, "/RH", RegisterHandler);

            //设置监听连接为websocket
            mg_set_protocol_http_websocket(nc);
            s_http_server_opts.document_root = "web";

            mg_set_timer(nc, mg_time()+SESSION_CHECK_INTERVAL);
        }

启动服务器

		void Start()
        {
            int timeout = 1000000;
            while(!quit)
            {
                mg_mgr_poll(&mgr, timeout);
               // cout << "time out" << endl;
            }
        }

回调函数

 //回调函数
        static void EventHandler(mg_connection* nc, int ev, void* data)
        {
            switch(ev)
            {
                case MG_EV_HTTP_REQUEST:
                    {
                        cout << "http request" << endl;
                        //获取整个http请求信息
                        struct http_message* hm = (struct http_message*)data;
                        string uri = Util::MgStrToString(&hm->uri);
                        cout << "debug: " << uri << endl;
                        if(uri.empty() || uri == "/" || uri == "/index.html")
                        {
                            if(sn.IsLogin(hm))
                            {
                                mg_serve_http(nc, hm, s_http_server_opts);
                            }
                            else
                            {
                                mg_http_send_redirect(nc, 302, mg_mk_str("/login.html"), mg_mk_str(NULL));
                            }
                        }
                        else
                        {
                            mg_serve_http(nc, hm, s_http_server_opts);
                        }
                        nc->flags |= MG_F_SEND_AND_CLOSE;
                    }
                    break;
                case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
                    {
                        //广播把消息发给所有人
                        Broadcast(nc, "some body join...");
                    }
                    break;
                //提取出发出去的websocket数据
                case MG_EV_WEBSOCKET_FRAME:
                    {
                        struct websocket_message *wm = (struct websocket_message*)data;
                        struct mg_str ms = {(const char*)wm->data, wm->size};
                        //把数据转成字符串
                        string msg = Util::MgStrToString(&ms);
                        Broadcast(nc, msg);
                    }
                    break;
                case MG_EV_CLOSE:
              //      cout << "link quit..." << endl;
                    break;
                case MG_EV_TIMER:
                    sn.CheckSession();
                    mg_set_timer(nc, mg_time()+SESSION_CHECK_INTERVAL);
                default:
            //        cout << "other ev:" << ev << endl;
                    break;
            }
        }

广播功能的实现

 		static void Broadcast(struct mg_connection* nc, string msg)
        {
            struct mg_connection *c;
            //链表头部赋给c
            for(c = mg_next(nc->mgr, NULL);c != NULL; c = mg_next(nc->mgr, c))
            {
                //向特定连接发送消息
                mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, msg.c_str(), msg.size());
            }
        }

以上就是代码主要功能点的介绍,详细代码请参考https://github.com/sunshineyam/project

你可能感兴趣的:(Linux)