服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++ select模型简单聊天室的实现示例

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

2022-11-24 11:26ufgnix0802 C/C++

本文主要介绍了C++ select模型简单聊天室的实现示例,使用CMake项目进行开发,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

TIPS:以下使用CMake项目进行开发。关于何为CMake,链接:http://www.tuohang.net/article/255349.html

简单聊天室效果展示

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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;
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 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模型简单聊天室内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq135595696/article/details/124153499

延伸 · 阅读

精彩推荐