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"); // 超时后输出提示信息。可以根据需求进行其他处理。例如,可以设置一个标志位表示超时,在主线程中检查该标志位并做出相应处理。同时,也可以在超时后直接退出线程处理函数。根据具体需求进行选择。这里简单输出提示信息。}
}