使用QTcpServer创建一个简单的服务器程序之二:多线程服务器(4)-服务端实现
程序员文章站
2024-03-20 17:19:22
...
前面说了服务端类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,真正进行服务端/客户端通信时,需要对信息进行封包和拆包处理,包括心跳机制等,我这里测试用的就是简单的发送字符串。
下一篇: 二分查找模板代码-java