使用QTcpServer创建一个简单的服务器程序之二:多线程服务器(4)-服务端实现

前面说了服务端类MyTcpServer只负责监听连入的客户端,并把这个客户端丢入线程池中。并且还要接收来自界面类的一些请求,并最终通过它管理的线程池来实现。这其中最重要函数就是重写incomingConnection

//这里包含一个线程池的对象和一个客户端链表
    MyThreadPool m_pool;//线程池
    QList<MyTcpSocket*> m_list;//维护一个客户端的列表,这个列表只是给界面显示使用,具体的和客户端通信都是交给线程池去完成

//还要改写最大连接数,不然默认的只能连接30个,这里我传入的是1000
void MyTcpServer::setMaxPendingConnections(int numConnections)
{
    QTcpServer::setMaxPendingConnections(numConnections);
}

//核心步骤,重写该函数,接管客户端socket连接进来后的操作
void MyTcpServer::incomingConnection(qintptr handle)
{
    //把客户端socket放入正确的线程中
    MyTcpSocket *pSocket = m_pool.AssignClient(handle);

    //注意!!!!!!!!!!!!!!!!!!!要用得到的实际信息设置pSocket对象中两个成员变量
    pSocket->setIP(pSocket->peerAddress().toString());
    pSocket->setPort(pSocket->peerPort());

    //加入客户端列表
    QMutexLocker lock(&m_lock);
    m_list.append(pSocket);

    //通知主界面,有新客户端加入
    emit SignalNewClient(pSocket);
}

负责和客户端通信的MyTcpSocket很简单,只要记录这个客户端的IP地址、端口号和socket描述符信息即可。

class MyTcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit MyTcpSocket(qintptr socketDescriptor, QObject *parent = 0);

private:
    QString ip;
    int port;
    qintptr socketID;

public:
    void setIP(const QString &ip);
    QString getIP()const;

    void setPort(int port);
    int getPort()const;

    qintptr getSocketID() const;

public slots:
    void SlotWriteData(const int handle,const QByteArray &buf);//发数据

};


MyTcpSocket::MyTcpSocket(qintptr socketDescriptor, QObject *parent) :
    QTcpSocket(parent),socketID(socketDescriptor)
{
    ip = "127.0.0.1";
    port = 6000;
    this->setSocketDescriptor(socketDescriptor);//传入socket描述符
    //connect(this,&MyTcpSocket::disconnected,this,&MyTcpSocket::deleteLater);
}

void MyTcpSocket::setIP(const QString &ip)
{
    this->ip = ip;
}

QString MyTcpSocket::getIP() const
{
    return this->ip;
}

void MyTcpSocket::setPort(int port)
{
    this->port = port;
}

int MyTcpSocket::getPort() const
{
    return this->port;
}

qintptr MyTcpSocket::getSocketID() const
{
    return socketID;
}

void MyTcpSocket::SlotWriteData(const int handle,const QByteArray &buf)
{
    if(socketID == (qintptr)handle)
        write(buf);
}

到这里这个简单的服务器程序就写的差不多了。当然,这只是一个简单的示例程序,还有很多可以改进的地方,我现在能想到的有以下几个地方:

1,放入线程池中的客户端指针可以采用智能指针,这样的话处理断开连接的信号时,客户端可以先处理自己的disconnect,然后再去处理线程池中的存放在指针以及服务端维护的客户端链表。

2,每个客户端类还可以带一个大一点的数据缓冲区,防止数据发送频繁时有数据丢失。

3,多线程处理的地方不知道有没有问题,我没有彻底的检查

4,真正进行服务端/客户端通信时,需要对信息进行封包和拆包处理,包括心跳机制等,我这里测试用的就是简单的发送字符串。

 

代码我已经上传到论坛,下载地址为:https://download.csdn.net/download/zouyang85457013/12274113

本程序使用的开发环境为Qt Creator,编译器为MinGW,Qt版本是5.1

发布了24 篇原创文章 · 获赞 1 · 访问量 2137
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览