聊天室

引言

现今,网络聊天是我们生活常见的一种沟通方式,而且社交工具层出不穷。
前段时间也爆发了一场“三英战吕布的大戏”,“马桶MT”、“多闪”、“聊天宝”同日向“微信发起挑战”。这足以说明现今社交软件真的是竞争激烈。

既然它这么火热,我们是不是应该来深入了解这个聊天系统是什么?怎么实现?
PS:在这里所实现的并不能像日常见到的软件那样丰富多彩。没错,就是黑框框,但也足以让我们对聊天系统的技术有启蒙意义。

预期实现

用户注册
用户登陆	
群聊

原理

 注册&登陆

在这里插入图片描述
注册
  用户选择注册接口,向服务器提供用户信息;
  服务器记录用户提供的信息,并返回给用户一个ID账号;
  注册成功的同时,将用户插入到我们的ID->用户的映射表中。
登陆
用户选择登陆接口,输入自己的账号和密码;
服务器通过查找映射表,匹对用户账号和密码;
匹对认证成功后,返回登陆成功,刷新出聊天界面。

 聊天

在这里插入图片描述
作为聊天室,一定是有多个数据的接收和发送。
我们这里是通过创建一个数据池,如果我们数据池未满,服务器将接收到的数据放入到数据池中,数据池如果不为空再从数据池中去取数据,之后将数据发送给各个用户。

具体实现

  注册&登陆

  由于注册和登陆这里牵扯到用户的信息传输和认证,所以我们这里选择使用可靠的TCP协议实现。
  为方便之后UDP的使用,封装一个Sock接口,通过传入类型选择是使用TCP还是UDP。

class SocketApi{

    public:
        static int Socket(int type){

            int sock = socket(AF_INET, type, 0);
            if(sock < 0){
                LOG("Socket error!", ERROR);
                exit(2);
            }
            return sock;
        }

        static void Bind(int sock, int port){

            struct sockaddr_in local;
            local.sin_family = AF_INET;
            local.sin_addr.s_addr = htonl(INADDR_ANY);
            local.sin_port = htons(port);

            if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0){
                LOG("Bind error", ERROR);
                exit(3);
            }
        }

        static void Listen(int sock){

            if(listen(sock, BACKLOG) < 0){
                LOG("Listen error", ERROR);
                exit(4);
            }
        }

        static int Accept(int listen_sock, std::string &net_ip, int &net_port){

            struct sockaddr_in peer; // 远端信息,客户端通过accept后两个参数传信息
            socklen_t len = sizeof(peer);
            int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
            if(sock < 0){

                LOG("Accept error", WARING);
                return -1;
            }
            net_ip = inet_ntoa(peer.sin_addr); 
            net_port = htons(peer.sin_port);
            return sock;
        }

        static bool Connect(const int &sock, std::string peer_ip,const int &port){

            struct sockaddr_in peer;
            peer.sin_family = AF_INET;
            peer.sin_addr.s_addr = inet_addr(peer_ip.c_str());
            peer.sin_port = htons(port);

            if(connect(sock, (struct sockaddr*)&peer, sizeof(peer)) < 0){
                LOG("Connect error!", WARING);
                return false;
            }
            return true;
        }
  注册协议格式

  为了规范用户信息,自定义一个注册协议,方便用户注册,也方便管理。

struct RegisterInfo{
	char nick_name[32];
	char school[64];
	char passwd[32];
};
struct LoginInfo{
	id_type id;
	char passwd[32];
};
struct Reply{
	int status;
	id_type id;
};
  通信协议

  仿照HTTP协议自定义属于我们自定义的协议格式。

class Request{
public:
    std::string method;
    std::string content_length; // 正文长度
    std::string blank;
    std::string text;

Request()
        :blank("\n")
    {}

    ~Request()
    {}
};

  method方法中就放入我们所需的功能:注册,登陆,退出。

  聊天协议格式

  聊天的数据传输可以使用UDP协议提高我们信息传输效率。

  客户端界面

  通过引用ncurses库,编写客户端界面。

    Window()
    {
        initscr();
        curs_set(0);
        pthread_mutex_init(&lock, NULL);
    }

    void SafeWrefresh(WINDOW *w){
        pthread_mutex_lock(&lock);
        wrefresh(w);
        pthread_mutex_unlock(&lock);
    }

    void DrawHeader(){
        int h = LINES*0.2;
        int w = COLS;
        int y = 0;
        int x = 0;
        header = newwin(h,w,y,x);
        box(header, 0, 0);
        SafeWrefresh(header);
    }

    void DrawInput(){
        int h = LINES*0.2;
        int w = COLS;
        int y = LINES*0.8;
        int x = 0;
        input = newwin(h,w,y,x);
        box(input, 0, 0);
        const string tips = "Please Enter#:";
        PutStringToWin(input, 2, 2, tips);
        SafeWrefresh(input);
    }

    void DrawOutput(){
        int h = LINES*0.6;
        int w = COLS*0.75;
        int y = LINES*0.2;
        int x = 0;
        output = newwin(h,w,y,x);
        box(output, 0, 0);
        SafeWrefresh(output);
    }

    void DrawOnline(){
        int h = LINES*0.6;
        int w = COLS*0.25;
        int y = LINES*0.2;
        int x = COLS*0.75;
        online = newwin(h,w,y,x);
        box(online, 0, 0);
        SafeWrefresh(online);
    }

效果展示

注册:
在这里插入图片描述
登陆:
在这里插入图片描述
聊天:
在这里插入图片描述

项目代码

https://github.com/Timecur/ChatRoom

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值