使用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

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值