从套接字接收线程中的消息
Posted
技术标签:
【中文标题】从套接字接收线程中的消息【英文标题】:Receving message in thread from socket 【发布时间】:2015-10-15 09:17:00 【问题描述】:我正在编写一个套接字程序并在一个线程中接收一条消息。但是我遇到了分段错误。 当我直接接收而不启动线程时,没有这样的问题(显示在注释部分)。
在下面的代码中,我直接接收并将其发送给客户端。部分代码如下所示:
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.
【问题讨论】:
调试器说什么? 具体是什么指令给出了分段错误? 显示 valgrind 输出。 虽然解决了NULL流的问题,但我想知道您是否需要删除流指针。我还建议使用 C++ 线程构造而不是 pthread。 【参考方案1】:TCPStream* stream = NULL; // HERE
ssize_t len;
char line[256];
while ((len = stream->receive(line, sizeof(line))) > 0) // HERE
您在 NULL
指针上调用 receive
。 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
的第四个参数:
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;
// ^^^^^^^^^^^^^^^^
【讨论】:
谢谢。那么我需要如何声明 TCPStream *stream 对象 .Globally? @user2357643 全局或(最好)将其作为第四个参数传递给pthread_create
。
我将它作为第四个参数传递。现在显示为警告:valgrind 的系统调用 read() 中的文件描述符 96707392 无效并且无法接收消息。但现在没有分段错误【参考方案2】:
在显示 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。
【讨论】:
@user2357643:这是因为“直接”代码有一个指向stream
对象的非 NULL 指针(由 accept()
返回),而 connection_handler
代码已初始化它的同名变量stream
到NULL
。这两个变量没有自动连接,->receive()
调用使用它正在执行的范围内可见的任何一个。以上是关于从套接字接收线程中的消息的主要内容,如果未能解决你的问题,请参考以下文章
Xamarin/WinForms 客户端在双线程架构中发送/接收时无法连接到套接字