QTcpSocket 은 생성된 쓰레드 외에 다른 쓰레드에서 write 를 시도할 경우 에러를 리턴하며 전송이 되지않는다. 이럴 경우 아래와 같이 이벤트를 발생시켜 생성 쓰레드에서 write 처리를 하도록해서 문제를 해결할 수 있다.
#ifndef TCPAUDIOSENDER_H #define TCPAUDIOSENDER_H #include <QThread> #include <QTcpServer> #include <QTcpSocket> #include <QMutex> #include "logwriter.h" #include "bufferqueue.h" class TcpAudioSender : public QThread { Q_OBJECT public: explicit TcpAudioSender(BufferQueue<AudioBuffer> *pSendQue, QThread *parent = 0); virtual ~TcpAudioSender(); signals: void socketWriteEvent(QTcpSocket *sock, AudioBuffer *buffer); public slots: void onNewConnection(); void onSocketStateChanged(QAbstractSocket::SocketState socketState); void onReadyRead();
void onSocketWrite(QTcpSocket *sock, AudioBuffer *buffer);
public: bool startServer(int port); void stopServer(); protected: virtual void run() override; protected: bool m_bRun; QTcpServer* m_pServer; int m_nPort; QList<QTcpSocket*> m_clientList; QMutex m_clientListMutex; BufferQueue<AudioBuffer>* m_pSendQue; LogWriter* m_pLogWriter; }; #endif // TCPAUDIOSENDER_H
#include "tcpaudiosender.h" TcpAudioSender::TcpAudioSender(BufferQueue<AudioBuffer> *pSendQue, QThread *parent) : QThread(parent) { m_bRun = false; m_pServer = new QTcpServer(this); m_pSendQue = pSendQue; m_pLogWriter = LogWriter::getInstance(); } TcpAudioSender::~TcpAudioSender() { delete m_pServer; } bool TcpAudioSender::startServer(int port) { if (!m_pServer->listen(QHostAddress::Any, port)) { m_pLogWriter->writeLog(QString("TcpAudioSender cannot open %1 port").arg(port)); return false; } m_nPort = port; connect(m_pServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
connect(this, SIGNAL(socketWriteEvent(QTcpSocket*, AudioBuffer*)), this, SLOT(onSocketWrite(QTcpSocket*, AudioBuffer*)));
m_bRun = true; QThread::start(); return true; } void TcpAudioSender::stopServer() { m_pServer->close(); m_bRun = false; QThread::wait(); } void TcpAudioSender::onNewConnection() { QTcpSocket *clientSocket = m_pServer->nextPendingConnection(); connect(clientSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead())); connect(clientSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChanged(QAbstractSocket::SocketState))); m_clientListMutex.lock(); m_clientList.push_back(clientSocket); m_clientListMutex.unlock(); } void TcpAudioSender::onSocketStateChanged(QAbstractSocket::SocketState socketState) { if (socketState == QAbstractSocket::UnconnectedState) { QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender()); m_clientListMutex.lock(); m_clientList.removeOne(sender); m_clientListMutex.unlock(); } } void TcpAudioSender::onReadyRead() { /* QTcpSocket* sender = static_cast<QTcpSocket*>(QObject::sender()); QByteArray datas = sender->readAll(); for (QTcpSocket* socket : m_clientList) { if (socket != sender) socket->write(QByteArray::fromStdString(sender->peerAddress().toString().toStdString() + ": " + datas.toStdString())); } */ }
void TcpAudioSender::onSocketWrite(QTcpSocket *sock, AudioBuffer *buffer) { int res = sock->write(buffer->data, buffer->size); if (res != buffer->size) { qDebug() << QString("TcpAudioSender(%1) cannot send client : %2, %3").arg(m_nPort).arg(res).arg(buffer->size); } delete buffer; //qDebug() << "TcpAudioSender send :" << size << "bytes"; }
void TcpAudioSender::run() { while (m_bRun) { AudioBuffer *buffer = m_pSendQue->pop(); if (!buffer) { usleep(10); continue; } m_clientListMutex.lock(); for (QTcpSocket* socket : m_clientList) { AudioBuffer *sendBuffer = new AudioBuffer(buffer->data, buffer->size);
emit socketWriteEvent(socket, sendBuffer);
} m_clientListMutex.unlock(); delete buffer; } }