QT socket과 Thread에 관한 질문입니다.

chobozzang의 이미지

qt 로 client ui 프로그램을 작성하고 있습니다.
서버에서 socket으로 약 1초에 2~3번 정도 뿌려주는 데이터를 ui에서 표시해야 하고, 가끔 설정을 서버로 전송해줘야 하는데요.
ui에 부하가 심할까봐 백그라운드로 socket 으로 들어오는 패킷을 읽으려고 하는데요. Thread 를 생성해 thread 내부에서 QTcpSocket을 할당해주고 읽으려고 하는데

qsocketnotifier socket notifiers cannot be disabled from another thread
qsocketnotifier socket notifiers cannot be enabled from another thread

이런 오류가 자꾸 뜨네요... 어쩔땐 제대로 된 값을 읽구요.
Qt socket을 처음 써봐서 잘못된 방식으로 쓰고 있는 것 같은데요... 고수님들의 조언 좀 부탁드리겠습니다. 현재 제가 테스트하려고 한 관련 소스도 첨부합니다.

sockThread::sockThread(QObject *parent) :
    QThread(parent)
{
    stopped = true;
    port = 0;
    ip = "";
    size = 0;
    memset(buff, 0, MAXLEN);
    header_size = sizeof(msgHeader);
 
    g_class.cli = new QTcpSocket();
    cli = g_class.cli;
}
 
 
sockThread::~sockThread()
{
    cli->disconnectFromHost();
    if(cli->waitForDisconnected(1000))
    {
        qDebug() << __func__ << " Disconnected!!";
    }
    if(cli) delete cli;
}
 
 
void sockThread::startsign(QString ip_, int port_)
{
    ip = ip_;
    port = port_;
 
    cli->connectToHost(ip, port);
 
    qDebug() << "Connecting..";
    if(!cli->waitForConnected(1000))
    {
        qDebug() << "Error: " << cli->errorString();
        return;
    }
 
    stopped = false;
}
 
void sockThread::stop()
{
    stopped = true;
    cli->disconnectFromHost();
    if(cli->waitForDisconnected(1000))
    {
        qDebug() << __func__ << " Disconnected!!";
    }
}
 
 
void sockThread::run()
{
 
    while(1)
    {
        if(stopped) continue;
 
        qDebug() << "sockThread thread start";
 
        if(!cli->waitForReadyRead())
        {
            qDebug() << "timeout occurred";
            continue;
        }
 
        size = 0;
        size = cli->read(buff, MAXLEN);
 
        dist_packet(buff, size);
    }
}
gilgil의 이미지

dist_packet은 뭐하는 건가요?

chobozzang의 이미지

그 부분은 제가 따로 구현한 함수이구요... buffer 에 값을 가지고 처리하는 것이라 소켓과는 무관한 동작이여서 포함시키지 않았습니다.

gilgil의 이미지

socket 얘기가 아니구요, UI처리는 thread switching을 해서 main thread에서 해 줘야 하기 때문에 물어 본 겁니다.

라스코니의 이미지

이유는 잘 모르겠지만 waitForReadyRead()를 non-blocking의 read() 같은 걸로 바꿔보세요.

klyx의 이미지

QThread::run() 안에서 소켓을 만들어보세요.

chobozzang의 이미지

감사합니다. ^^ run 안에서 하니 동작이 되네요. 궁금한게 하나 있는데요... run 함수는 별개로 동작하는 쓰레드 같은데 여기서만 소켓을 쓸수 있는건가요? 현재 qthread::run() 에선 받는 역활만 하고 있는데 가끔 서버쪽으로 소켓을 전송해줘야 할 때도 있는데 다른 방식이 있을까요?

klyx의 이미지

'소켓을 전송한다'가 무슨 뜻인가요? 어떤건지 모르겠지만 아무튼 별도의 스레드에서 소켓통신을 하고 싶으시면 그 스레드 안에서 소켓을 만드셔야합니다.

chobozzang의 이미지

소켓으로 데이터를 전송한다는 뜻이였구요... 제가 접속해야 할 서버가 client 수를 1개로 제한하고 있어서 이미 receive 받아야 할 thread에서 접속해 있기에 새로 만들 수가 없어서요.. ㅠㅠ

klyx의 이미지

그 받는 소켓으로 보내면되죠.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.