从套接字接收线程中的消息

时间:2015-10-15 09:17:01

标签: c++ multithreading sockets

我正在编写套接字程序并在线程中接收消息。但是我遇到了分段错误。 当我在没有启动线程的情况下直接收到时,没有这样的问题(在注释部分中显示)。

在下面的代码中我直接收到并发送给客户端。代码的部分如下所示:

if (acceptor->start() == 0)
    {
        while (1)
        {
            stream = acceptor->accept();
            if (stream != NULL)
            {
                /*
                ssize_t len;
                char line[256];
                while ((len = stream->receive(line, sizeof(line))) > 0) {
                    line[len] = 0;
                    printf("received - %s\n", line);
                    stream->send(line, len);
                */    
                pthread_t sniffer_thread;
                if( pthread_create( &sniffer_thread, NULL, connection_handler,NULL) < 0)
                {
                     perror("could not create thread");
                     return 1;
                }
                //Now join the thread , so that we dont terminate before the thread
                pthread_join( sniffer_thread , NULL);
             }
                delete stream;
          }
       }
    exit(0);

现在,我在线程函数中收到相同的内容。它显示了分段错误。

代码如下所示。

void *connection_handler(void *arg)
{
    TCPStream* stream = NULL;
    ssize_t len;
    char line[256];
    while ((len = stream->receive(line, sizeof(line))) > 0)
    {
        line[len] = 0;
        printf("received - %s\n", line);
        stream->send(line, len);
    }
}

Valgrind输出的一部分是

==5163== Memcheck, a memory error detector
==5163== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==5163== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==5163== Command: ./appdownload 9999 192.5.60
==5163== 
==5163== Thread 2:
==5163== Invalid read of size 4
==5163==    at 0x401975: TCPStream::receive(char*, unsigned long, int) (tcpstream.cpp:30)
==5163==    by 0x40177B: connection_handler(void*) (appdownload.cpp:68)
==5163==    by 0x4E3F181: start_thread (pthread_create.c:312)
==5163==    by 0x566947C: clone (clone.S:111)
==5163==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5163== 
==5163== 
==5163== Process terminating with default action of signal 11 (SIGSEGV)
==5163==  Access not within mapped region at address 0x0
==5163==    at 0x401975: TCPStream::receive(char*, unsigned long, int) (tcpstream.cpp:30)
==5163==    by 0x40177B: connection_handler(void*) (appdownload.cpp:68)
==5163==    by 0x4E3F181: start_thread (pthread_create.c:312)
==5163==    by 0x566947C: clone (clone.S:111)
==5163==  If you believe this happened as a result of a stack
==5163==  overflow in you`enter code here`r program's main thread (unlikely but
==5163==  possible), you can try to increase the size of the
==5163==  main thread stack using the --main-stacksize= flag.
==5163==  The main thread stack size used in this run was 8388608.

2 个答案:

答案 0 :(得分:4)

TCPStream* stream = NULL; // HERE
ssize_t len;
char line[256];
while ((len = stream->receive(line, sizeof(line))) > 0) // HERE

您在receive指针上调用NULL。 Valgrind告诉你:

==5163== Thread 2:
==5163== Invalid read of size 4
==5163==    at 0x401975: TCPStream::receive(char*, unsigned long, int) (tcpstream.cpp:30) // HERE
==5163==    by 0x40177B: connection_handler(void*) (appdownload.cpp:68)
==5163==    by 0x4E3F181: start_thread (pthread_create.c:312)
==5163==    by 0x566947C: clone (clone.S:111)
==5163==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
              //  ^- HERE

如果需要将TCPStream*从主线程传递到新线程函数,可以使用pthread_create的第4个参数:

  

pthread_create()函数在调用中启动一个新线程   处理。新线程通过调用start_routine()开始执行;   arg作为start_routine()的唯一参数传递。   (来源:man pthread_create

主线程:

TCPStream *stream = acceptor->accept();
(...)
pthread_create( &sniffer_thread, NULL, connection_handler, stream)
                                                      //   ^^^^^^

工作人员主题:

void *connection_handler(void *arg)
{
    TCPStream* stream = (TCPStream *)arg;
    //                  ^^^^^^^^^^^^^^^^

答案 1 :(得分:1)

在你展示了你的valgrind跟踪之后,显然你只是在空指针上调用receive

嗯,让我们看看。

char line[256];                                              // 256 bytes space
while ((len = stream->receive(line, sizeof(line))) > 0)      // receive up to 256 bytes
{
    line[len] = 0;                                           // put 257th byte in

我猜你可以为0再使用一个字节 - 尝试最多接收sizeof(line)-1

或者只使用std::vector,然后使用push_back那个0。