通过socketpair+select实现线程同步的用法代码

2023-12-14 20:32:56

1,socketpair详细用法说明

socketpair()是一个Unix/Linux系统调用,用于创建一个本地端对(socket pair)。它创建两个已连接的socket描述符,用于在同一进程中的两个不同线程之间进行通信。

以下是socketpair()函数的详细用法说明:

#include <sys/socket.h>  
#include <unistd.h>  
  
int socketpair(int domain, int type, int protocol, int sv[2]);

参数说明:

domain:指定要使用的协议域,通常是AF_UNIX或AF_INET。
type:指定要创建的套接字的类型,可以是SOCK_STREAM(流套接字)或SOCK_DGRAM(数据报套接字)。
protocol:指定要使用的具体协议,对于大多数应用程序来说,通常设置为0。
sv:这是一个长度为2的整数数组,用于存储创建的两个套接字的描述符。

返回值:

如果成功,socketpair()返回0,否则返回-1并设置errno表示错误码。

2,select的用法说明

Select则是一种用于监视多个文件描述符(包括套接字)的变化情况的方法。它通常用于非阻塞式I/O操作,可以同时监视多个文件描述符的状态(如可读、可写或异常等)。Select通常用于异步或事件驱动的程序中,可以提高程序的效率和响应速度。

在使用Select时,需要创建一个select()函数,指定要监视的文件描述符集合以及等待的时间。在select()函数返回后,可以根据文件描述符的状态进行相应的读写操作。Select的使用需要结合事件循环和回调函数等机制来实现异步I/O操作。

需要注意的是,Socketpair和Select的使用场景和目的不同,应该根据具体的需求选择合适的工具。同时,在使用Socketpair和Select时,需要注意它们的错误处理和异常情况的处理,以确保程序的稳定性和可靠性。

3,使用socketpair和select实现线程同步

下面是一个使用socketpair和select实现两个线程同步的参考代码:

#include <stdio.h>  
#include <stdlib.h>  
#include <sys/socket.h>  
#include <unistd.h>  
#include <string.h>  
#include <pthread.h>  
#include <sys/select.h>  
#include <sys/time.h>  
  
#define BUFFER_SIZE 1024  
  
void *thread_func(void *arg) {  
    int sockfd = *((int *)arg);  
    char buffer[BUFFER_SIZE];  
    fd_set readfds;  
    struct timeval tv;  
    int n;  
    char message[] = "Hello from sub thread";  
  
    while (1) {  
        FD_ZERO(&readfds);  
        FD_SET(sockfd, &readfds);  
        tv.tv_sec = 1;  // 设置超时时间为1秒  
        tv.tv_usec = 0;  
        n = select(sockfd + 1, &readfds, NULL, NULL, &tv);  
        if (n == -1) {  
            perror("select");  
            exit(EXIT_FAILURE);  
        } else if (FD_ISSET(sockfd, &readfds)) {  
            n = recv(sockfd, buffer, BUFFER_SIZE, 0);  
            buffer[n] = '\0';  
            printf("Thread received: %s\n", buffer);  
        } else {  
            printf("Timeout\n");  
            break;  
        }  
        send(sockfd, message, strlen(message), 0);  
    }  
    close(sockfd);  
    return NULL;  
}  
  
int main() {  
    int sockfd[2];  
    pthread_t thread;  
    char message[] = "Hello from main thread";  
  
    // 创建socketpair  
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) == -1) {  
        perror("socketpair");  
        exit(EXIT_FAILURE);  
    }  
  
    // 创建线程并传递socket的文件描述符  
    if (pthread_create(&thread, NULL, thread_func, &sockfd[0]) != 0) {  
        perror("pthread_create");  
        exit(EXIT_FAILURE);  
    }  
  
    // 发送消息给线程,并等待接收消息的超时时间设置为1秒  
    send(sockfd[1], message, strlen(message), 0);  
    struct timeval tv;  
    tv.tv_sec = 1;  // 设置超时时间为1秒  
    tv.tv_usec = 0;  
    fd_set readfds;  
    int n;  
    while (1) {  
        FD_ZERO(&readfds);  
        FD_SET(sockfd[1], &readfds);  
        n = select(sockfd[1] + 1, &readfds, NULL, NULL, &tv);  
        if (n == -1) {  
            perror("select");  
            exit(EXIT_FAILURE);  
        } else if (FD_ISSET(sockfd[1], &readfds)) {  
            n = recv(sockfd[1], buffer, BUFFER_SIZE, 0);  
            buffer[n] = '\0';  
            printf("Main received: %s\n", buffer);  
            break;  // 接收消息,跳出循环等待线程发送消息或超时后退出线程处理函数。  
        } else {  
            printf("Timeout\n");  // 超时后输出提示信息。可以根据需求进行其他处理。例如,可以设置一个标志位表示超时,在主线程中检查该标志位并做出相应处理。同时,也可以在超时后直接退出线程处理函数。根据具体需求进行选择。这里简单输出提示信息。
        }
}

文章来源:https://blog.csdn.net/jiangchaobing_2017/article/details/135002407
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。