Socket每次write()后使用flush()清空缓存使消息马上发送到服务端,否则debug版本会出现心跳不及时发送现象;
除此之外debug版本比较稳定。现在测试release版本时,发现客户端运行一段时间后(半个小时左右,不做任何操作,程序内部会每隔4秒向服务端发送一次心跳)就会出现runtime error,试过很多方法都没有效果,但是发现把每次write()完的flush()操作注释掉以后就比较稳定。请问flush()是否会导致程序不稳定?
6 个解决方案
#1
flush不可能会让它不稳定的,这个你要绝对相信的.
这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
#2
可能flush不是引起问题的真正原因,但是注释掉以后确实变得稳定了。我在使用socket时做了互斥,我们的框架设计是登陆和心跳一定要使用同一个socket。
#3
哎...我猜我肯定解释不清楚,如果你贴代码,到可以看下.
socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作.
还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作.
还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
#4
线程是用Windows的API创建的
QTcpSocket* g_tcpSocket = new QTcpSocket();
HANDLE g_handleHeartBeat = CreateThread(NULL, 0, RunHeartBeat, g_Client, 0, NULL); // 创建心跳线程
DWORD WINAPI RunHeartBeat(LPVOID param)
{
WaitForSingleObject(g_hMutex, INFINITE);
Request request; // 需要向服务端发送的内容
//.....填写request
int nleft, nbytes;
char* ptr = (char*)&request;
nleft = 12; // 需要发送的长度
for (; nleft > 0; )
{
nbytes = g_tcpSocket->write(ptr, nleft);
g_tcpSocket->flush(); // 注释掉这行以后release版本就稳定了,但是debug版本不会及时发出消息
if (nbytes <= 0)
{
// .......
ReleaseMutex(g_hMutex);
return -1;
}
nleft -= nbytes;
ptr += nbytes;
}
ReleaseMutex(g_hMutex);
}
主线程基本是一样的代码。能帮忙看一下吗,多谢!
#5
差点凌乱了..这混合编程用得....目测你的问题应该是混合编程引起的
我给你贴一个处理了write函数的QTcpSocket,这个socket被我移动到一个单独的线程里面去了,但它write函数是线程安全的. 如果你有什么其它的函数接口需要调用m_pQTcpSocket的,像我那样写一个信号一个槽,然后连接起来,间接调用...这样可以保证m_pQTcpSocket在一个线程里面被使用.
这里问题来了,你可能会觉得这样写很麻烦或者不习惯.这个没有办法.如果你要用windows线程或者编程思想,处理Qt
的东西,真的会很纠结.. 貌似QTcpSocket在不同的Qt线程里面,调用它会报错(QSocketNotifier: socket notifiers cannot be enabled from another thread)..这里你的为什么没有报错,我估计就是因为你是windows的线程原因..不知道我有没有说错.
这里要么你使用windows的socket要么你使用Qt的线程..如果使用Qt的线程,又要说一堆...这个问题就真的复杂起来了....我只能帮你到这里了.
#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H
#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QHostAddress>
class MyTcpSocket : public QThread
{
Q_OBJECT
public:
MyTcpSocket()
: m_pQTcpSocket(new QTcpSocket())
{
this->start();
this->moveToThread(this);
m_pQTcpSocket->moveToThread(this);
connect(this, SIGNAL(DoMyWrite(QByteArray)),
this, SLOT(OnMyWrite(QByteArray)));
connect(this, SIGNAL(DoMyConnect()),
this, SLOT(OnMyConnectToHost()));
}
~MyTcpSocket()
{
this->exit();
this->wait(10 * 1000);
}
void myWrite(const char *data, qint64 len)
{
emit DoMyWrite(QByteArray(data, len));
}
void myConnectToHost()
{
emit DoMyConnect();
}
signals:
void DoMyWrite(const QByteArray &data);
void DoMyConnect();
private slots:
void OnMyWrite(const QByteArray &data)
{
qDebug() << "write" << QThread::currentThreadId();
m_pQTcpSocket->write(data);
m_pQTcpSocket->flush();
}
void OnMyConnectToHost()
{
qDebug() << "myConnect" << QThread::currentThreadId();
m_pQTcpSocket->connectToHost(QHostAddress::LocalHost, 8811);
}
private:
QTcpSocket * const m_pQTcpSocket;
};
#endif // MYTCPSOCKET_H
#6
谢谢,改用定时器确实不会有这问题了。
#1
flush不可能会让它不稳定的,这个你要绝对相信的.
这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
#2
flush不可能会让它不稳定的,这个你要绝对相信的.
这里很有可能是你的线程不安全引起的,,Socket貌似不能跨线程使用的吧.
可能flush不是引起问题的真正原因,但是注释掉以后确实变得稳定了。我在使用socket时做了互斥,我们的框架设计是登陆和心跳一定要使用同一个socket。
#3
哎...我猜我肯定解释不清楚,如果你贴代码,到可以看下.
socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作.
还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作.
还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
#4
哎...我猜我肯定解释不清楚,如果你贴代码,到可以看下.
socket貌似只能工作在一个线程里面..你用两个线程,里终也是合并到一个线程工作.
还有就是如果你用Qt写代码的话,我可以很确定的说,你可能一辈子也用不到互斥锁了.Qt信号槽就可以保证线程安全
线程是用Windows的API创建的
QTcpSocket* g_tcpSocket = new QTcpSocket();
HANDLE g_handleHeartBeat = CreateThread(NULL, 0, RunHeartBeat, g_Client, 0, NULL); // 创建心跳线程
DWORD WINAPI RunHeartBeat(LPVOID param)
{
WaitForSingleObject(g_hMutex, INFINITE);
Request request; // 需要向服务端发送的内容
//.....填写request
int nleft, nbytes;
char* ptr = (char*)&request;
nleft = 12; // 需要发送的长度
for (; nleft > 0; )
{
nbytes = g_tcpSocket->write(ptr, nleft);
g_tcpSocket->flush(); // 注释掉这行以后release版本就稳定了,但是debug版本不会及时发出消息
if (nbytes <= 0)
{
// .......
ReleaseMutex(g_hMutex);
return -1;
}
nleft -= nbytes;
ptr += nbytes;
}
ReleaseMutex(g_hMutex);
}
主线程基本是一样的代码。能帮忙看一下吗,多谢!
#5
主线程基本是一样的代码。能帮忙看一下吗,多谢!
差点凌乱了..这混合编程用得....目测你的问题应该是混合编程引起的
我给你贴一个处理了write函数的QTcpSocket,这个socket被我移动到一个单独的线程里面去了,但它write函数是线程安全的. 如果你有什么其它的函数接口需要调用m_pQTcpSocket的,像我那样写一个信号一个槽,然后连接起来,间接调用...这样可以保证m_pQTcpSocket在一个线程里面被使用.
这里问题来了,你可能会觉得这样写很麻烦或者不习惯.这个没有办法.如果你要用windows线程或者编程思想,处理Qt
的东西,真的会很纠结.. 貌似QTcpSocket在不同的Qt线程里面,调用它会报错(QSocketNotifier: socket notifiers cannot be enabled from another thread)..这里你的为什么没有报错,我估计就是因为你是windows的线程原因..不知道我有没有说错.
这里要么你使用windows的socket要么你使用Qt的线程..如果使用Qt的线程,又要说一堆...这个问题就真的复杂起来了....我只能帮你到这里了.
#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H
#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QHostAddress>
class MyTcpSocket : public QThread
{
Q_OBJECT
public:
MyTcpSocket()
: m_pQTcpSocket(new QTcpSocket())
{
this->start();
this->moveToThread(this);
m_pQTcpSocket->moveToThread(this);
connect(this, SIGNAL(DoMyWrite(QByteArray)),
this, SLOT(OnMyWrite(QByteArray)));
connect(this, SIGNAL(DoMyConnect()),
this, SLOT(OnMyConnectToHost()));
}
~MyTcpSocket()
{
this->exit();
this->wait(10 * 1000);
}
void myWrite(const char *data, qint64 len)
{
emit DoMyWrite(QByteArray(data, len));
}
void myConnectToHost()
{
emit DoMyConnect();
}
signals:
void DoMyWrite(const QByteArray &data);
void DoMyConnect();
private slots:
void OnMyWrite(const QByteArray &data)
{
qDebug() << "write" << QThread::currentThreadId();
m_pQTcpSocket->write(data);
m_pQTcpSocket->flush();
}
void OnMyConnectToHost()
{
qDebug() << "myConnect" << QThread::currentThreadId();
m_pQTcpSocket->connectToHost(QHostAddress::LocalHost, 8811);
}
private:
QTcpSocket * const m_pQTcpSocket;
};
#endif // MYTCPSOCKET_H
#6
主线程基本是一样的代码。能帮忙看一下吗,多谢!
差点凌乱了..这混合编程用得....目测你的问题应该是混合编程引起的
我给你贴一个处理了write函数的QTcpSocket,这个socket被我移动到一个单独的线程里面去了,但它write函数是线程安全的. 如果你有什么其它的函数接口需要调用m_pQTcpSocket的,像我那样写一个信号一个槽,然后连接起来,间接调用...这样可以保证m_pQTcpSocket在一个线程里面被使用.
这里问题来了,你可能会觉得这样写很麻烦或者不习惯.这个没有办法.如果你要用windows线程或者编程思想,处理Qt
的东西,真的会很纠结.. 貌似QTcpSocket在不同的Qt线程里面,调用它会报错(QSocketNotifier: socket notifiers cannot be enabled from another thread)..这里你的为什么没有报错,我估计就是因为你是windows的线程原因..不知道我有没有说错.
这里要么你使用windows的socket要么你使用Qt的线程..如果使用Qt的线程,又要说一堆...这个问题就真的复杂起来了....我只能帮你到这里了.
#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H
#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QHostAddress>
class MyTcpSocket : public QThread
{
Q_OBJECT
public:
MyTcpSocket()
: m_pQTcpSocket(new QTcpSocket())
{
this->start();
this->moveToThread(this);
m_pQTcpSocket->moveToThread(this);
connect(this, SIGNAL(DoMyWrite(QByteArray)),
this, SLOT(OnMyWrite(QByteArray)));
connect(this, SIGNAL(DoMyConnect()),
this, SLOT(OnMyConnectToHost()));
}
~MyTcpSocket()
{
this->exit();
this->wait(10 * 1000);
}
void myWrite(const char *data, qint64 len)
{
emit DoMyWrite(QByteArray(data, len));
}
void myConnectToHost()
{
emit DoMyConnect();
}
signals:
void DoMyWrite(const QByteArray &data);
void DoMyConnect();
private slots:
void OnMyWrite(const QByteArray &data)
{
qDebug() << "write" << QThread::currentThreadId();
m_pQTcpSocket->write(data);
m_pQTcpSocket->flush();
}
void OnMyConnectToHost()
{
qDebug() << "myConnect" << QThread::currentThreadId();
m_pQTcpSocket->connectToHost(QHostAddress::LocalHost, 8811);
}
private:
QTcpSocket * const m_pQTcpSocket;
};
#endif // MYTCPSOCKET_H
谢谢,改用定时器确实不会有这问题了。