QT:Qsocket长连接的实现(单线程服务器)
来源:互联网 发布:淘宝如何入驻全球购 编辑:程序博客网 时间:2024/04/27 15:11
废话少说:直接上代码
代码功能:客户端先向服务发送一个字符串,服务器收到后,再向客户端发送一个同样的字符串(回射字符串)
这个DEMO的服务器端已经在2012-2-14大幅度更新了,之前的程序存在有严重的问题(内存泄露,不释放端口。。。),
我也是新手,请大家见谅,如果大家发现这个DEMO还有什么问题,欢迎留言和建议。大家共同学习。
源代码:
//服务器端 //server.h #ifndef CHATSERVER_H #define CHATSERVER_H #include <QtGui> #include <QtNetwork> #include <QtCore> class ConnectSocket : public QTcpSocket { Q_OBJECT public: ConnectSocket(QObject* parent=0); ~ConnectSocket(); void SetDescriptor(int des) { m_Descriptor = des; }signals: void disconnectedSignal(int); private slots: void readMessage(); void sendMessage(); void disconnectSlot();private: //网络断开后,描述符会立即变成-1,所以要先保存一下int m_Descriptor;QString m_String; quint16 m_BlockSize; }; class Server : public QTcpServer { Q_OBJECT public: Server(QObject *parent = 0,int port=0); protected: void incomingConnection(int socketDescriptor); private: QMap<int, ConnectSocket*> m_ClientDesMap;public slots: void clientDisconnected(int); }; class Dialog : public QDialog { Q_OBJECT public: Dialog(QWidget *parent = 0); private: QLabel *statusLabel; QPushButton *quitButton; Server *server; }; #endif // CHATSERVER_H //server.cpp #include "server.h" Server::Server(QObject *parent,int port) : QTcpServer(parent) { if( !listen(QHostAddress::Any,port) ) { QMessageBox::about(NULL, "Error", "Can't connected"); exit(2); } } void Server::incomingConnection(int descriptor) { ConnectSocket *socket = new ConnectSocket(this); connect(socket, SIGNAL(disconnectedSignal(int)), this, SLOT(clientDisconnected(int))); socket->setSocketDescriptor(descriptor);//CommectSocket*一定要保存,否则连接会自动断开 m_ClientDesMap[descriptor] = socket;qDebug() << descriptor << " added";socket->SetDescriptor(descriptor);}void Server::clientDisconnected(int descriptor) { //连接结束一定要删除对应的socket,否则会造成内存泄漏。m_ClientDesMap[descriptor]->deleteLater();m_ClientDesMap.remove(descriptor);qDebug() << descriptor << " removed";} Dialog::Dialog(QWidget *parent) :QDialog(parent) { statusLabel = new QLabel; quitButton = new QPushButton(tr("Quit")); quitButton->setAutoDefault(false); server=new Server(this,8888); if (!server->isListening()) { QMessageBox::critical(this, tr("Chat Server"), tr("Unable to start the server: %1.") .arg(server->errorString())); close(); return; } QString ipAddress; QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); for (int i = 0; i < ipAddressesList.size(); ++i) { if (ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { ipAddress = ipAddressesList.at(i).toString(); break; } } if (ipAddress.isEmpty()) ipAddress = QHostAddress(QHostAddress::LocalHost).toString(); statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.") .arg(ipAddress).arg(server->serverPort())); connect(quitButton,SIGNAL(clicked()),this,SLOT(close())); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); buttonLayout->addStretch(1); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(statusLabel); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); setWindowTitle(tr("Chat Server")); } ConnectSocket::ConnectSocket(QObject* parent) { m_BlockSize = 0; connect(this,SIGNAL(readyRead()),this,SLOT(readMessage())); connect(this,SIGNAL(disconnected()),this,SLOT(disconnectSlot())); qDebug() << this << " created";} ConnectSocket::~ConnectSocket() { qDebug() << this << " deleted";} void ConnectSocket::readMessage() { QDataStream in(this); in.setVersion(QDataStream::Qt_4_0); if (m_BlockSize == 0) { if (bytesAvailable() < (int)sizeof(quint16)) return; in >> m_BlockSize; } if (bytesAvailable() < m_BlockSize) return; in >> m_String; m_BlockSize = 0; sendMessage(); } void ConnectSocket::sendMessage() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); out << (quint16)0; out << m_String; out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16)); write(block); } void ConnectSocket::disconnectSlot(){emit disconnectedSignal(m_Descriptor);}//main.cpp #include "server.h" #include <QtGui/QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Dialog w; w.show(); return a.exec(); } //客户端 //client.h #ifndef TRYCLI_H_ #define TRYCLI_H_ #include <QtNetwork> #include <QtGui> #include <QtCore> class Client : public QWidget { Q_OBJECT private: bool isConnected; QLineEdit *serverIpEdit; QLabel *label; QLineEdit *strEdit; QPushButton *startButton; QTcpSocket *tcpClient; quint16 blockSize; QString sendString; QString readString; public: Client(); ~Client(); public slots: void displayError(QAbstractSocket::SocketError socketError); void newConnect(); void readMessage(); void sendMessage(); }; #endif //client.cpp #include "client.h" #include <QtGui/QMessageBox> #include <QtGui/QHBoxLayout> #include <QtEvents> Client::Client() { setWindowTitle("Client"); resize(300, 100); serverIpEdit = new QLineEdit("127.0.0.1"); startButton = new QPushButton("start"); strEdit = new QLineEdit; label = new QLabel("Emtpy"); isConnected = false; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(serverIpEdit); layout->addWidget(label); layout->addWidget(strEdit); layout->addWidget(startButton); setLayout(layout); tcpClient = new QTcpSocket(this); connect(startButton, SIGNAL(clicked()), this, SLOT(newConnect())); connect(tcpClient, SIGNAL(connected()), this, SLOT(sendMessage())); connect(tcpClient, SIGNAL(readyRead()), this, SLOT(readMessage())); connect(tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(displayError(QAbstractSocket::SocketError))); } Client::~Client() { } void Client::newConnect() { blockSize = 0; if(!isConnected) { tcpClient->abort(); tcpClient->connectToHost(serverIpEdit->text(), 8888); isConnected = true; } else sendMessage(); } void Client::sendMessage() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_4_0); sendString = strEdit->text(); out << (quint16)0; out << sendString; out.device()->seek(0); out << (quint16)(block.size() - sizeof(quint16)); tcpClient->write(block); } void Client::readMessage() { QDataStream in(tcpClient); in.setVersion(QDataStream::Qt_4_0); if (blockSize == 0) { if (tcpClient->bytesAvailable() < (int)sizeof(quint16)) return; in >> blockSize; } if (tcpClient->bytesAvailable() < blockSize) return; in >> readString; label->setText(readString); } void Client::displayError(QAbstractSocket::SocketError socketError) { switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: QMessageBox::information(this, tr("Fortune Client"), tr("The host was not found. Please check the " "host name and port settings.")); break; case QAbstractSocket::ConnectionRefusedError: QMessageBox::information(this, tr("Fortune Client"), tr("The connection was refused by the peer. " "Make sure the fortune server is running, " "and check that the host name and port " "settings are correct.")); break; default: QMessageBox::information(this, tr("Fortune Client"), tr("The following error occurred: %1.") .arg(tcpClient->errorString())); } } //main.cpp #include "client.h" #include <QtGui/QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Client w; w.show(); return a.exec(); }
- QT:Qsocket长连接的实现(单线程服务器)
- QT:Qsocket长连接的实现(多线程服务器)
- QT:Qsocket长连接的实现(多线程服务器)
- http服务器长连接的实现
- VB服务器长连接实现
- QT中的QSOCKET编程
- 服务器进程间RPC长连接实现的思考
- HTTP长连接实现“服务器推”的技术
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)
- 基于Java Socket的自定义协议,实现Android与服务器的长连接(一)
- “长连接”方式实现服务器推送
- 单台服务器百万并发长连接支持
- APP长连接的实现
- 如何实现单服务器300万个长连接的?
- java实现tcp服务器(单线程、多线程)、客户端
- 【Android开发】如何实现android和服务器长连接呢?推送消息的原理
- 为你的Java应用嵌入一个功能强大的文字编辑器
- 创建表单
- 深入理解Android消息处理系统——Looper、Handler、Thread
- 类与继承
- 最近点对问题
- QT:Qsocket长连接的实现(单线程服务器)
- 测试php源文编码对定义在源文件中的中文字符数据写入Mysql数据库后编码的影响
- 怎样快速挖掘网站的长尾关键词 ?
- 在linux下编译运行c语言程序
- freemarker
- C++面试宝典2011版
- Redmine安装
- MOSS 中出现 unexpect error
- VC如何查看全局变量的值