C- Unix套接字 - 非阻塞读取

wil*_*ill 5 c unix sockets multithreading

我正在尝试制作一个简单的客户端 - 服务器聊天程序.在客户端,我分拆另一个线程来读取服务器上的任何输入数据.问题是,当一个人从主线程注销时,我想优雅地终止第二个线程.我试图使用共享变量'running'来终止,问题是,socket read()命令是一个阻塞命令,所以如果我这样做(运行== 1),服务器必须在读取之前发送一些东西并且可以再次检查while条件.我正在寻找一种方法(仅使用常见的unix套接字)来执行非阻塞读取,基本上某种形式的peek()可以工作,因为我可以不断检查循环以查看我是否已完成.

读取线程循环在下面,现在它没有任何共享变量的互斥锁,但我打算稍后添加,不要担心!;)

void *serverlisten(void *vargp)
{
    while(running == 1)
    {
        read(socket, readbuffer, sizeof(readbuffer));
        printf("CLIENT RECIEVED: %s\n", readbuffer);
    }
    pthread_exit(NULL);
}
Run Code Online (Sandbox Code Playgroud)

fgh*_*ghj 8

您可以使socket不可阻塞,如另一篇文章中所建议的那样使用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
Run Code Online (Sandbox Code Playgroud)


Kar*_*ath 7

fcntl(socket, F_SETFL, O_NONBLOCK);
Run Code Online (Sandbox Code Playgroud)

或者,如果你有其他标志:

int x;
x=fcntl(socket ,F_GETFL, 0);
fcntl(socket, F_SETFL, x | O_NONBLOCK);
Run Code Online (Sandbox Code Playgroud)

然后检查读取的返回值以查看是否有可用数据.

注意:一些谷歌搜索会产生很多完整的例子.

您还可以使用阻塞套接字,并select在超时时"查看" .这似乎更合适,所以你不要忙等待.