fix:forward情况下,connectto里面固定延时1000不合理,有的手机卡,需要2000甚至更高,改为定时重试策略

This commit is contained in:
Barry 2019-06-20 15:59:46 +08:00
parent f5a9a399f0
commit 08da6cfbc1
2 changed files with 101 additions and 63 deletions

View file

@ -20,7 +20,7 @@ Server::Server(QObject *parent) : QObject(parent)
QTcpSocket* tmp = m_serverSocket.nextPendingConnection();
if (dynamic_cast<VideoSocket*>(tmp)) {
m_videoSocket = dynamic_cast<VideoSocket*>(tmp);
if (!m_videoSocket->isValid() || !readInfo(m_deviceName, m_deviceSize)) {
if (!m_videoSocket->isValid() || !readInfo(m_videoSocket, m_deviceName, m_deviceSize)) {
stop();
emit connectToResult(false);
}
@ -164,63 +164,7 @@ bool Server::connectTo()
return true;
}
// device server need time to start
// TODO:电脑配置太低的话这里有可能时间不够导致连接太早安卓监听socket还没有建立
// 后续研究其他办法
// wait for devices server start
QTimer::singleShot(1000, this, [this](){
QString deviceName;
QSize deviceSize;
bool success = false;
// video socket
m_videoSocket = new VideoSocket();
m_videoSocket->connectToHost(QHostAddress::LocalHost, m_params.localPort);
if (!m_videoSocket->waitForConnected(1000)) {
stop();
qWarning("video socket connect to server failed");
emit connectToResult(false, "", QSize());
return false;
}
// control socket
m_controlSocket = new QTcpSocket();
m_controlSocket->connectToHost(QHostAddress::LocalHost, m_params.localPort);
if (!m_controlSocket->waitForConnected(1000)) {
stop();
qWarning("control socket connect to server failed");
emit connectToResult(false, "", QSize());
return false;
}
if (QTcpSocket::ConnectedState == m_videoSocket->state()) {
// connect will success even if devices offline, recv data is real connect success
// because connect is to pc adb server
m_videoSocket->waitForReadyRead(1000);
// devices will send 1 byte first on tunnel forward mode
QByteArray data = m_videoSocket->read(1);
if (!data.isEmpty() && readInfo(deviceName, deviceSize)) {
success = true;
} else {
qWarning("video socket connect to server read device info failed");
success = false;
}
} else {
qWarning("connect to server failed");
m_videoSocket->deleteLater();
success = false;
}
if (success) {
// we don't need the adb tunnel anymore
disableTunnelForward();
m_tunnelEnabled = false;
} else {
stop();
}
emit connectToResult(success, deviceName, deviceSize);
});
startConnectTimeoutTimer();
return true;
}
@ -229,6 +173,8 @@ void Server::timerEvent(QTimerEvent *event)
if (event && m_acceptTimeoutTimer == event->timerId()) {
stopAcceptTimeoutTimer();
emit connectToResult(false, "", QSize());
} else if (event && m_connectTimeoutTimer == event->timerId()) {
onConnectTimer();
}
}
@ -317,14 +263,14 @@ bool Server::startServerByStep()
return stepSuccess;
}
bool Server::readInfo(QString &deviceName, QSize &size)
bool Server::readInfo(VideoSocket* videoSocket, QString &deviceName, QSize &size)
{
unsigned char buf[DEVICE_NAME_FIELD_LENGTH + 4];
if (m_videoSocket->bytesAvailable() <= (DEVICE_NAME_FIELD_LENGTH + 4)) {
m_videoSocket->waitForReadyRead(300);
if (videoSocket->bytesAvailable() <= (DEVICE_NAME_FIELD_LENGTH + 4)) {
videoSocket->waitForReadyRead(300);
}
qint64 len = m_videoSocket->read((char*)buf, sizeof(buf));
qint64 len = videoSocket->read((char*)buf, sizeof(buf));
if (len < DEVICE_NAME_FIELD_LENGTH + 4) {
qInfo("Could not retrieve device information");
return false;
@ -352,6 +298,93 @@ void Server::stopAcceptTimeoutTimer()
}
}
void Server::startConnectTimeoutTimer()
{
stopConnectTimeoutTimer();
m_connectTimeoutTimer = startTimer(100);
}
void Server::stopConnectTimeoutTimer()
{
if (m_connectTimeoutTimer) {
killTimer(m_connectTimeoutTimer);
m_connectTimeoutTimer = 0;
}
m_connectCount = 0;
}
void Server::onConnectTimer()
{
// device server need time to start
// 这里连接太早时间不够导致安卓监听socket还没有建立readInfo会失败所以采取定时重试策略
// 每隔100ms尝试一次最多尝试100次
QString deviceName;
QSize deviceSize;
bool success = false;
VideoSocket* videoSocket = new VideoSocket();
videoSocket->connectToHost(QHostAddress::LocalHost, m_params.localPort);
if (!videoSocket->waitForConnected(1000)) {
// 连接到adb很快的这里失败不重试
m_connectCount = 10;
qWarning("video socket connect to server failed");
goto result;
}
QTcpSocket *controlSocket = new QTcpSocket();
controlSocket->connectToHost(QHostAddress::LocalHost, m_params.localPort);
if (!controlSocket->waitForConnected(1000)) {
// 连接到adb很快的这里失败不重试
m_connectCount = 10;
qWarning("control socket connect to server failed");
goto result;
}
if (QTcpSocket::ConnectedState == videoSocket->state()) {
// connect will success even if devices offline, recv data is real connect success
// because connect is to pc adb server
videoSocket->waitForReadyRead(1000);
// devices will send 1 byte first on tunnel forward mode
QByteArray data = videoSocket->read(1);
if (!data.isEmpty() && readInfo(videoSocket, deviceName, deviceSize)) {
success = true;
goto result;
} else {
qWarning("video socket connect to server read device info failed, try again");
goto result;
}
} else {
qWarning("connect to server failed");
m_connectCount = 10;
goto result;
}
result:
if (success) {
stopConnectTimeoutTimer();
m_videoSocket = videoSocket;
m_controlSocket = controlSocket;
// we don't need the adb tunnel anymore
disableTunnelForward();
m_tunnelEnabled = false;
emit connectToResult(success, deviceName, deviceSize);
return;
}
if (videoSocket) {
videoSocket->deleteLater();
}
if (controlSocket) {
controlSocket->deleteLater();
}
if (10 <= m_connectCount++) {
stopConnectTimeoutTimer();
stop();
emit connectToResult(false);
}
}
void Server::onWorkProcessResult(AdbProcess::ADB_EXEC_RESULT processResult)
{
if (sender() == &m_workProcess) {

View file

@ -65,9 +65,12 @@ private:
bool disableTunnelForward();
bool execute();
bool startServerByStep();
bool readInfo(QString& deviceName, QSize& size);
bool readInfo(VideoSocket* videoSocket, QString& deviceName, QSize& size);
void startAcceptTimeoutTimer();
void stopAcceptTimeoutTimer();
void startConnectTimeoutTimer();
void stopConnectTimeoutTimer();
void onConnectTimer();
private:
QString m_serverPath = "";
@ -79,6 +82,8 @@ private:
bool m_tunnelEnabled = false;
bool m_tunnelForward = false; // use "adb forward" instead of "adb reverse"
quint32 m_acceptTimeoutTimer = 0;
quint32 m_connectTimeoutTimer = 0;
quint32 m_connectCount = 0;
QString m_deviceName = "";
QSize m_deviceSize = QSize();
ServerParams m_params;