📄 connection.cpp
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the example classes of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "connection.h"#include <QtNetwork>static const int TransferTimeout = 30 * 1000;static const int PongTimeout = 60 * 1000;static const int PingInterval = 5 * 1000;static const char SeparatorToken = ' ';Connection::Connection(QObject *parent) : QTcpSocket(parent){ greetingMessage = tr("undefined"); username = tr("unknown"); state = WaitingForGreeting; currentDataType = Undefined; numBytesForCurrentDataType = -1; transferTimerId = 0; isGreetingMessageSent = false; pingTimer.setInterval(PingInterval); QObject::connect(this, SIGNAL(readyRead()), this, SLOT(processReadyRead())); QObject::connect(this, SIGNAL(disconnected()), &pingTimer, SLOT(stop())); QObject::connect(&pingTimer, SIGNAL(timeout()), this, SLOT(sendPing())); QObject::connect(this, SIGNAL(connected()), this, SLOT(sendGreetingMessage()));}QString Connection::name() const{ return username;}void Connection::setGreetingMessage(const QString &message){ greetingMessage = message;}bool Connection::sendMessage(const QString &message){ if (message.isEmpty()) return false; QByteArray msg = message.toUtf8(); QByteArray data = "MESSAGE " + QByteArray::number(msg.size()) + " " + msg; return write(data) == data.size();}void Connection::timerEvent(QTimerEvent *timerEvent){ if (timerEvent->timerId() == transferTimerId) { abort(); killTimer(transferTimerId); transferTimerId = 0; }}void Connection::processReadyRead(){ if (state == WaitingForGreeting) { if (!readProtocolHeader()) return; if (currentDataType != Greeting) { abort(); return; } state = ReadingGreeting; } if (state == ReadingGreeting) { if (!hasEnoughData()) return; buffer = read(numBytesForCurrentDataType); if (buffer.size() != numBytesForCurrentDataType) { abort(); return; } username = QString(buffer) + "@" + peerAddress().toString() + ":" + QString::number(peerPort()); currentDataType = Undefined; numBytesForCurrentDataType = 0; buffer.clear(); if (!isValid()) { abort(); return; } if (!isGreetingMessageSent) sendGreetingMessage(); pingTimer.start(); pongTime.start(); state = ReadyForUse; emit readyForUse(); } do { if (currentDataType == Undefined) { if (!readProtocolHeader()) return; } if (!hasEnoughData()) return; processData(); } while (bytesAvailable() > 0);}void Connection::sendPing(){ if (pongTime.elapsed() > PongTimeout) { abort(); return; } write("PING 1 p");}void Connection::sendGreetingMessage(){ QByteArray greeting = greetingMessage.toUtf8(); QByteArray data = "GREETING " + QByteArray::number(greeting.size()) + " " + greeting; if (write(data) == data.size()) isGreetingMessageSent = true;}int Connection::readDataIntoBuffer(int maxSize){ if (maxSize > MaxBufferSize) return 0; int numBytesBeforeRead = buffer.size(); if (numBytesBeforeRead == MaxBufferSize) { abort(); return 0; } while (bytesAvailable() > 0 && buffer.size() < maxSize) { buffer.append(read(1)); if (buffer.endsWith(SeparatorToken)) break; } return buffer.size() - numBytesBeforeRead;}int Connection::dataLengthForCurrentDataType(){ if (bytesAvailable() <= 0 || readDataIntoBuffer() <= 0 || !buffer.endsWith(SeparatorToken)) return 0; buffer.chop(1); int number = buffer.toInt(); buffer.clear(); return number;}bool Connection::readProtocolHeader(){ if (transferTimerId) { killTimer(transferTimerId); transferTimerId = 0; } if (readDataIntoBuffer() <= 0) { transferTimerId = startTimer(TransferTimeout); return false; } if (buffer == "PING ") { currentDataType = Ping; } else if (buffer == "PONG ") { currentDataType = Pong; } else if (buffer == "MESSAGE ") { currentDataType = PlainText; } else if (buffer == "GREETING ") { currentDataType = Greeting; } else { currentDataType = Undefined; abort(); return false; } buffer.clear(); numBytesForCurrentDataType = dataLengthForCurrentDataType(); return true;}bool Connection::hasEnoughData(){ if (transferTimerId) { QObject::killTimer(transferTimerId); transferTimerId = 0; } if (numBytesForCurrentDataType <= 0) numBytesForCurrentDataType = dataLengthForCurrentDataType(); if (bytesAvailable() < numBytesForCurrentDataType || numBytesForCurrentDataType <= 0) { transferTimerId = startTimer(TransferTimeout); return false; } return true;}void Connection::processData(){ buffer = read(numBytesForCurrentDataType); if (buffer.size() != numBytesForCurrentDataType) { abort(); return; } switch (currentDataType) { case PlainText: emit newMessage(username, QString::fromUtf8(buffer)); break; case Ping: write("PONG 1 p"); break; case Pong: pongTime.restart(); break; default: break; } currentDataType = Undefined; numBytesForCurrentDataType = 0; buffer.clear();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -