C++ select模型简单聊天室的实现示例

 更新时间:2022年05月07日 09:28:41   作者:ufgnix0802  
本文主要介绍了C++ select模型简单聊天室的实现示例,使用CMake项目进行开发,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

TIPS:以下使用CMake项目进行开发。关于何为CMake,链接:https://www.jb51.net/article/247089.htm

简单聊天室效果展示

简单聊天室服务端源码(使用select模型)

// Server0327.cpp: 定义应用程序的入口点。
//

#include "Server0327.h"
#include <WinSock2.h>
#include <vector>

#pragma comment(lib,"ws2_32.lib")

using namespace std;
class TcpServer
{
public:
    bool Listen(const char* ip, int port)
    {
        //创建socket
        _serverSock = socket(AF_INET, SOCK_STREAM, 0);
        if (INVALID_SOCKET == _serverSock)
            goto Exit;
        //绑定IP和端口号
        SOCKADDR_IN addr;
        addr.sin_addr.s_addr = inet_addr(ip);
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        if (INVALID_SOCKET == bind(_serverSock, (sockaddr*)&addr, sizeof(SOCKADDR_IN)))
            goto Exit;

        //监听端口
        if (INVALID_SOCKET == listen(_serverSock, 255))
            goto Exit;

        return true;
    Exit:
        closesocket(_serverSock);
        _serverSock = INVALID_SOCKET;
        return false;
    }


    void Update()
    {
        FD_SET reads;
        FD_ZERO(&reads);
        FD_SET(_serverSock, &reads);

        for (auto&& clientSock : _clientSocks)
            FD_SET(clientSock, &reads);

        int nRet = select(0, &reads, nullptr, nullptr, nullptr);
        if (nRet > 0)
        {
            if (FD_ISSET(_serverSock, &reads))
                Accept();
            else
            {
                for (int i = 0; i < _clientSocks.size(); i++)
                {
                    if (FD_ISSET(_clientSocks[i], &reads))
                    {
                        char buf[1024]{ 0 };
                        int nRecv = recv(_clientSocks[i], buf, 1024, 0);
                        if (nRecv > 0)
                            OnNetMsg(_clientSocks[i], buf, sizeof(buf));
                        if (nRecv <= 0)
                        {
                            closesocket(_clientSocks[i]);
                            OnDisConnect(_clientSocks[i]);
                            _clientSocks.erase(_clientSocks.begin() + i);
                            continue;
                        }
                    }
                }
            }
        }
    }

    void Accept()
    {
        SOCKADDR_IN clientAddr;
        int clientAddrLen = sizeof(clientAddr);
        SOCKET clientSock = accept(_serverSock, (sockaddr*)&clientAddr, &clientAddrLen);
        if (INVALID_SOCKET != clientSock)
        {
            _clientSocks.push_back(clientSock);
            OnConnect(clientSock);
        }

    }

    void OnConnect(SOCKET clientSock)
    {
        printf("%d 客户端连接\n", clientSock);
    }

    int OnNetMsg(SOCKET clientSock, const char* buff, int len)
    {
        printf("%d == %s\n", clientSock, buff);
        for (auto&& clientSock : _clientSocks)
            send(clientSock, buff, len, 0);
        return len;
    }


    void OnDisConnect(SOCKET sock)
    {
        printf("%d==客户端断开连接\n", sock);
    }

private:
    SOCKET _serverSock;
    vector<SOCKET> _clientSocks;
};

int main()
{
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);

    TcpServer server;
    server.Listen("0.0.0.0", 7890);
    while (true)
        server.Update();

    WSACleanup();
    return 0;
}

简单聊天室客户端源码(使用多线程)

// CMakeClient0331.cpp: 定义应用程序的入口点。
//

#include "CMakeClient0331.h"
#include<iostream>
#include<WinSock2.h>
#include<thread>

#pragma comment(lib,"ws2_32.lib")


int main()
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET clientSock = socket(AF_INET, SOCK_STREAM, 0);
    if (INVALID_SOCKET == clientSock)
    {
        closesocket(clientSock);
        WSACleanup();
        return 0;
    }

    SOCKADDR_IN serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serverAddr.sin_port = htons(7890);
    if (INVALID_SOCKET == connect(clientSock, (sockaddr*)&serverAddr, sizeof(SOCKADDR_IN)))
    {
        closesocket(clientSock);
        WSACleanup();
        return 0;
    }
    std::cout << "已连接服务端" << std::endl;

    std::thread t([&clientSock] {
        while (true)
        {
            char buf[1024]{ 0 };
            int nRecvLen = recv(clientSock, buf, 1024, 0);
            if (nRecvLen <= 0)
                break;
            std::cout << "接收数据长度:" << nRecvLen << " 接受数据:" << buf << std::endl;
        }
        });
    t.detach();

    while (true)
    {
        char buf[1024]{ 0 };
        std::cin >> buf;
        if (buf[0] == 'q')break;
        int nSendLen = send(clientSock, buf, sizeof(buf), 0);
    }

    closesocket(clientSock);
    WSACleanup();
    return 0;
}

到此这篇关于C++ select模型简单聊天室的文章就介绍到这了,更多相关C++ select模型简单聊天室内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言实现贪吃蛇小游戏

    C语言实现贪吃蛇小游戏

    这篇文章主要为大家详细介绍了C语言实现贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • C语言MFC导出dll回调函数方法详解

    C语言MFC导出dll回调函数方法详解

    这篇文章主要为大家介绍了C语言MFC导出dll回调函数方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • C语言数据结构之单链表与双链表的增删改查操作实现

    C语言数据结构之单链表与双链表的增删改查操作实现

    这篇文章主要为大家详细介绍了C语言数据结构中单链表与双链表的增删改查操作的实现,相信大家如果搞懂了本文内容,应对复杂的链表类的题也就能慢慢钻研了
    2022-07-07
  • C++ std::list的merge()使用方式与分析

    C++ std::list的merge()使用方式与分析

    这篇文章主要介绍了C++ std::list的merge()使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • C++内联函数详情

    C++内联函数详情

    这篇文章主要介绍了C++内联函数,文章主要围绕C++内联函数的相关资料展开详细内容,需要的朋友可以参考一下,希望对大家有所帮助
    2021-11-11
  • C++调用matlab函数的实例

    C++调用matlab函数的实例

    这篇文章主要介绍了C++调用matlab函数的方法,包括封装matlab函数,编译matlab函数及C++环境配置,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • MFC控件大小随窗体大小而改变

    MFC控件大小随窗体大小而改变

    本文给大家分享的是使用VC++根据对话框大小调整控件大小的方法和示例代码,有需要的小伙伴可以参考下。
    2015-06-06
  • c语言的形参和实参传递的区别详解

    c语言的形参和实参传递的区别详解

    这篇文章主要介绍了c语言的形参和实参传递的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C++  数据结构链表的实现代码

    C++ 数据结构链表的实现代码

    这篇文章主要介绍了C++ 数据结构链表的实现代码的相关资料,需要的朋友可以参考下
    2017-01-01
  • 解析取模运算% 和位与运算& 之间的关系详解

    解析取模运算% 和位与运算& 之间的关系详解

    本篇文章是对取模运算%和位与运算&之间的关系进行了详细的分析介绍,需要的朋友参考下
    2013-05-05

最新评论