C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ selec聊天室

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

作者: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模型简单聊天室内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文