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

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

你的鼓励将是我创作的最大动力
在这里插入图片描述

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基于UDP协议使用select实现多线程的服务器端代码的示例: ```c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<sys/socket.h> #include<arpa/inet.h> #include<netinet/in.h> #include<sys/select.h> #include<pthread.h> #define BUF_SIZE 1024 #define PORT 12345 void * handle_client(void * arg); int main() { int serv_sock, clnt_sock; struct sockaddr_in serv_addr, clnt_addr; socklen_t clnt_addr_size; char buf[BUF_SIZE]; fd_set reads, temps; int fd_max, fd_num, str_len; pthread_t t_id; serv_sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(PORT); if(bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) { perror("bind() error"); exit(1); } FD_ZERO(&reads); FD_SET(serv_sock, &reads); fd_max = serv_sock; while(1) { temps = reads; fd_num = select(fd_max+1, &temps, 0, 0, 0); if(fd_num == -1) break; for(int i=0; i<fd_max+1; i++) { if(FD_ISSET(i, &temps)) { if(i == serv_sock) { clnt_addr_size = sizeof(clnt_addr); str_len = recvfrom(serv_sock, buf, BUF_SIZE, 0, (struct sockaddr *)&clnt_addr, &clnt_addr_size); clnt_sock = i; FD_SET(clnt_sock, &reads); if(fd_max < clnt_sock) fd_max = clnt_sock; pthread_create(&t_id, NULL, handle_client, (void *)&clnt_sock); pthread_detach(t_id); } } } } close(serv_sock); return 0; } void * handle_client(void * arg) { int clnt_sock = *((int *)arg); char buf[BUF_SIZE]; int str_len; while(1) { str_len = recv(clnt_sock, buf, BUF_SIZE, 0); if(str_len == 0) { FD_CLR(clnt_sock, &reads); break; } else { send(clnt_sock, buf, str_len, 0); } } close(clnt_sock); return NULL; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤舟簔笠翁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值