C++ TCP多客户端通讯《服务端源码》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangfahe1/article/details/84027628

1、先看一下运行成果:

多客户端

服务器已经在之前启动,并且服务器被隐藏在后台,所以并不会显示出来。

 客户端之间聊天方式为:[客户端ID:聊天信息],例如:828:你是谁.

客户端与服务器之间:直接输入数字1-3

2、服务器代码分析

服务器头文件

class TCPServer
{

public:

    /* @接口 默认构造函数
     * @邮箱 [email protected]
     */
    TCPServer();

    /* @接口 默认析构函数
     * @邮箱 [email protected]
     */
    ~TCPServer();
    
    /* @接口 创建客户端ID
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 [email protected]
     */
    long createClientGuid();

    /* @接口 初始化服务器
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 [email protected]
     */
    virtual bool initServer();
    
    /* @接口 开始等待连接
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 [email protected]
     */
    virtual bool beginAccept(int count = 64);

    /* @接口 创建服务器,int为端口
     * @返回 bool 成功返回值为true,否则返回值为false
     * @邮箱 [email protected]
     */
    virtual bool createServer(int, const QString &ip = "127.0.0.1");

public:

    /* @接口 服务器套接字
     * @返回 bool 成功返回值为true,否则返回值为false
     * @作者 杨发荷 
     * @邮箱 [email protected]
     * @时间 2018年11月1号
     */
    SOCKET sock();
    
    /* @接口 接受信息
     * @返回 bool 成功返回值为true,否则返回值为false
     * @作者 杨发荷
     * @邮箱 [email protected]
     * @时间 2018年10月26号
     */
    QString recv(const SOCKET &);
    
    /* @接口 响应客户端
     * @参数 int 客户端标识ID,QString 客户端发过来的信息
     * @作者 杨发荷
     * @邮箱 [email protected]
     * @时间 2018年11月1号
     */
    void respondClient(int, const QString &);

    /* @接口 发送信息到指定的客户
     * @返回 bool 成功返回值为true,否则返回值为false
     * @作者 杨发荷
     * @邮箱 [email protected]
     * @时间 2018年10月26号
     */
    bool send(const SOCKET &, const QString &);
    
    /* @接口 服务器线程
     * @作者 杨发荷
     * @邮箱 [email protected]
     * @时间 2018年11月1号
     */
    static DWORD serverThread(LPVOID);

public:

    int m_listen;
    int m_current;
    SOCKET _socket;
    QList<SOCKET> m_socks;

};

服务器源文件

#include "server.h"

TCPServer::TCPServer()
:  m_listen(0)
, m_current(0)
{

}

TCPServer::~TCPServer()
{
    closesocket(_socket);
    WSACleanup();
}

SOCKET TCPServer::sock()
{
    return _socket;
}

QString TCPServer::recv(const SOCKET &_sock)
{
    int size = 4096; char buf[4096] = {0};
    int ret = ::recv(_sock, buf, size, 0);
    if(ret == -1) return "Exit";
    QString recvinfo = QString::fromLocal8Bit(buf, ret - 1);
    return recvinfo;
}

bool TCPServer::initServer()
{
    WSADATA wsa;
    int ret = WSAStartup(MAKEWORD(2, 2), &wsa);
    return ret != -1;
}

//接口作废

long TCPServer::createClientGuid()
{
    long val = rand() % 65536;
    //     if(!g_client.contains(val)) return val;
    //     for(;;)
    //     {
    //         val = rand() % 65536;
    //         if(!g_client.contains(val)) break;
    //     }
    return val;
}

bool TCPServer::beginAccept(int len)
{
    m_listen = len;
    listen(_socket, len);
    int size = sizeof(SOCKADDR);
    char buf[1024] = {0};
    sockaddr_in *addr_v4;
    while((len--) > 0)
    {
        SOCKADDR addr; SOCKET _sock;
        _sock = accept(_socket, (SOCKADDR *)&addr, &size);
        if(0 == getpeername(_sock, &addr, &size))
        {
            if(addr.sa_family == AF_INET)
                addr_v4 = (sockaddr_in*)&addr;
        }
        m_socks.append(_sock);  this->send(_sock, QS("%1").arg(_sock));
        HANDLE handle = CreateThread(NULL, 0, serverThread, this, 0, NULL);
        CloseHandle(handle);    m_current++;
    }
    return true;
}

void TCPServer::respondClient(int cur, const QString &cmd)
{
    int idx = 0; QString info;
    switch(cmd.toInt())
    {
        case 1:
            info = QS("client total:<%1> count.").arg(m_socks.length());
            break;
        case 2:
            info = QS("server listen <%1>, but connected <%2>, the server at best connecting <%3>").arg(m_listen).arg(m_current).arg(m_listen - m_current);
            break;
        case 3:
            for(idx = 0; idx < m_current - 1; ++idx)
                info += QS("client [%1] be connected.\n").arg(m_socks[idx]);
            info += QS("client [%1] be connected.").arg(m_socks.last());
            break;
    }
    if(info.length() != 0)
         this->send(m_socks[cur], info);
}

DWORD TCPServer::serverThread(LPVOID param)
{
    if(param == NULL) return -1;
    TCPServer *server = (TCPServer *)param;
    char Buffer[1024] = {0}; int cur = server->m_current - 1;
    while(true)
    {
        QString buf = server->recv(server->m_socks[cur]);
        if(buf.compare("pipe", Qt::CaseInsensitive) == 0)
        {
            dox::Object<dox::IPipeServer> pipe(NIL);
            pipe->initPipe(dox::IPipeServer::DoublePipe);
            dox::IPipeServer::PipeSyntony _syntony;
            pipe->pickChild(); pipe->setOutputType(&_syntony);
            pipe->createPipe(); pipe->createChild();
            while(true)
            {
                buf = server->recv(server->m_socks[cur]);
                if(buf.compare("exit", Qt::CaseInsensitive) == 0) break;
                pipe->writePipeData(buf);
                QString info = pipe->readPipeData();
                server->send(server->m_socks[cur], info);
            }
        }
        if(buf.compare("exit", Qt::CaseInsensitive) == 0)
        {
            closesocket(server->m_socks[cur]);
            server->m_socks.removeAt(cur);
            return -1;
        }
        if(buf == "Clear")
        {
            for(int idx = 0; idx < server->m_socks.length(); ++idx)
                closesocket(server->m_socks[idx]);
            return -1;
        }
        int pos = buf.indexOf(":");
        if(pos == -1)
            server->respondClient(cur, buf);
        else
        {
            long des_guid = buf.left(pos).toLong();
            buf = QS("%1%2").arg(server->m_socks[cur]).arg(buf.mid(pos));
            server->send(des_guid, buf);
        }
    }
    return 0;
}

bool TCPServer::createServer(int port, const QString &ip)
{
    _socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(_socket == INVALID_SOCKET) return false;
    sockaddr_in addrServ;
    memset(&addrServ, 0, sizeof(sockaddr_in));
    QString IP = ip.length() == 0 ? "127.0.0.1" : ip;
    addrServ.sin_family = AF_INET;
    addrServ.sin_port = htons(port);
    addrServ.sin_addr.s_addr = INADDR_ANY; //inet_addr(IP.toLocal8Bit().constData());
    int ret = bind(_socket, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
    return true;
}

bool TCPServer::send(const SOCKET &_sock, const QString &info)
{
    char sendinfo[4096] = {0};
    sprintf(sendinfo, "%s", info.toLocal8Bit().constData());
    ::send(_sock, sendinfo, info.length() + 1, NULL);
    return true;
}
//源文件结束

客户端代码将在下一篇文章中介绍。

猜你喜欢

转载自blog.csdn.net/yangfahe1/article/details/84027628