我正在试图做一个简单的客户端 – 服务器聊天程序。 在客户端,我分离出另一个线程,从服务器读取任何传入的数据。 问题是,当一个人从主线程注销时,我想优雅地终止第二个线程。 我试图使用共享variables'运行'来终止,问题是,套接字的read()命令是一个阻塞命令,所以如果我这样做(运行== 1),服务器必须发送一些东西之前的读取返回并且可以再次检查时间条件。 我正在寻找一种方法(只有普通的UNIX套接字)做一个非阻塞阅读,基本上某种forms的peek()将工作,因为我可以不断检查循环,看看我是否完成。
读线程循环在下面,现在它没有共享variables的任何互斥量,但我打算补充,以后不要担心! ;)
void *serverlisten(void *vargp) { while(running == 1) { read(socket, readbuffer, sizeof(readbuffer)); printf("CLIENT RECIEVED: %s\n", readbuffer); } pthread_exit(NULL); }
你可以使套接字不能阻塞,如在另一个帖子中建议加上使用select来等待输入超时,如下所示:
fd_set input; FD_ZERO(&input); FD_SET(sd, &input); struct timeval timeout; timeout.tv_sec = sec; timeout.tv_usec = msec * 1000; int n = select(sd + 1, &input, NULL, NULL, &timeout); if (n == -1) { //something wrong } else if (n == 0) continue;//timeout if (!FD_ISSET(sd, &input)) ;//again something wrong //here we can call not blockable read
fcntl(socket, F_SETFL, O_NONBLOCK);
或者,如果您有其他标志:
int x; x=fcntl(socket ,F_GETFL, 0); fcntl(socket, F_SETFL, x | O_NONBLOCK);
然后检查读取的返回值以查看是否有可用的数据。
注意:一点谷歌会给你很多完整的例子。
您也可以使用阻塞套接字,并select
超时“偷看”。 这里似乎更合适,所以你不要忙着等。
最好的办法是摆脱额外的线程,并使用select()
或poll()
来处理一个线程中的所有内容。
如果你想保持线程,你可以做的一件事就是使用SHUT_RDWR
在套接字上调用shutdown()
,这将关闭连接,唤醒被阻塞的所有线程,但保持文件描述符有效。 加入阅读器线程后,可以关闭套接字。 请注意,这只适用于套接字,而不适用于其他类型的文件描述符。
使用选项SO_RCVTIMEO
查找函数setsockopt
。
这可能不是你正在寻找的具体答案,但它可能是你可以找到它的地方。 我正在阅读:
Unix网络编程,第1卷:套接字网络API,第3版
还有很多多线程,非阻塞服务器和客户端的例子。 另外,他们解释了许多不同方法之间的推理和权衡。
希望有帮助…