【socket】 unix域套接字(socketpair )通信|socketpair和pipe的区别

socketpair机制

描述

先看下传统的CS模型,如下:

 

总是一方发起请求,等待另一方回应。当一次传输完成之后,client端发起新的请求之后,server端才作出回应。 那如何才能做到双向通信?  一种解决办法就是client端即使client,又是server,server端即使client也是server,如下:

 

但是上述方面比较复杂,这时候就引入要分析的socketpair了。

socketpair用于创建一对相互连接的unnamed socket。而pipe系统调用使用创建的pipe也是相互连接的unnamed pipe(无名管道)。而pipe和socketpair创建的描述符之间的区别就是:  pipe创建的描述符一端只能用于读,一端用于写,而socketpair创建的描述符任意一端既可以读也可以写。

原理

示例代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
 
#define SOCKET_BUFFER_SIZE      (32768U)
 
 
void *thread_function(void *arg)
{
    int len = 0;
    int fd  = *((int*)(arg));
    char buf[500];
    int cnt = 0;
 
    /*主线程*/
    while(1)
    {        
        /*向main thread线程发送数据*/
        len = sprintf(buf, "Hi, main process, cnt = %d", cnt++);
        write(fd, buf, len);
    
        /*读数据*/
        len = read(fd, buf, 500);
        buf[len]='\0';
        printf("%s\n",buf);
        
        sleep(5);    
    } 
    
    return NULL;
}
 
 
int main()
{
    int ret;
    int sockets[2];
    int bufferSize = SOCKET_BUFFER_SIZE;
    pthread_t thread;
    
    ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
    if(ret == -1)
    {
        printf("socketpair create error!\n");
        return -1;
    }
    
    
    /*设置socket描述符的选项*/
    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
 
    
    /*创建线程1*/
    pthread_create(&thread, NULL, thread_function, (void*)(&sockets[1]));
 
 
    int len = 0;
    int fd  = sockets[0];
    char buf[500];
    int cnt = 0;
 
    /*主线程*/
    while(1)
    {
        /*读数据*/
        len = read(fd, buf, 500);
        buf[len]='\0';
        printf("%s\n",buf);
        
        /*项thread线程发送数据*/
        len = sprintf(buf, "Hi, thread process, cnt = %d", cnt++);
        write(fd, buf, len);
    }
 
    return 0;
}

测试结果:

1.  编译代码

gcc socketpair.c -o socketpair -lpthread


2. 运行,查看结果

test$ ./socketpair

Hi, main process, cnt = 0

Hi, thread process, cnt = 0

Hi, main process, cnt = 1

Hi, thread process, cnt = 1

Hi, main process, cnt = 2

Hi, thread process, cnt = 2

注意:  socketpair创建的只适用于父子进程或者线程间通信,不能用于两个进程之间通信。如果要实现两个进程之间的双向通信,则需要将socketpair创建的一个描述符fd发送给另一个进程,这相当于两个两个不同的进程访问同一个文件。

socketpair和pipe的区别

(原文:https://blog.csdn.net/fangru/article/details/9041119#)

管道pipe是半双工的,pipe两次才能实现全双工,使得代码复杂。socketpair直接就可以实现全双工。

socketpair对两个文件描述符中的任何一个都可读和可写,而pipe是一个读,一个写。

详间代码:

一:pipe实现父子进程全双工通信:

#include <stdlib.h>
#include <stdio.h>
 
int main ()
{
    int fd1[2],fd2[2];
    pipe(fd1);
    pipe(fd2);
    if ( fork() ) {
        /* Parent process: echo client */
        int val = 0;
        close( fd1[0] );
        close(fd2[1]);
        while ( 1 ) {
            sleep( 1 );
            ++val;
            printf( "parent Sending data: %d\n", val );
            write( fd1[1], &val, sizeof(val) );
            read( fd2[0], &val, sizeof(val) );
            printf( "parent Data received: %d\n", val );
        }
    }
    else {
        /* Child process: echo server */
        int val ;
        close( fd1[1] );
        close(fd2[0]);
        while ( 1 ) {
            read( fd1[0], &val, sizeof(val) );
            printf( "son Data received: %d\n", val );
            ++val;
            write( fd2[1], &val, sizeof(val) );
            printf( "son send received: %d\n", val );
        }
    }
}

输出结果:parent Sending data: 1 
son Data received: 1 
son send received: 2 
parent Data received: 2 
parent Sending data: 3 
son Data received: 3 
son send received: 4 

parent Data received: 4

一:soketpair实现父子进程全双工通信:

#include <sys/types.h>
#include <sys/socket.h>
 
#include <stdlib.h>
#include <stdio.h>
 
int main ()
{
    int fd[2];
    int r = socketpair( AF_UNIX, SOCK_STREAM, 0, fd );
    if ( r < 0 ) {
        perror( "socketpair()" );
        exit( 1 );
    }   
    if ( fork() ) {
        /* Parent process: echo client */
        int val = 0;
        close( fd[1] );
        while ( 1 ) {
            sleep( 1 );
            ++val;
            printf( "parent Sending data: %d\n", val );
            write( fd[0], &val, sizeof(val) );
            read( fd[0], &val, sizeof(val) );
            printf( "parent Data received: %d\n", val );
 
        }
    }
    else {
        /* Child process: echo server */
        int val ;
        close( fd[0] );
        while ( 1 ) {
            read( fd[1], &val, sizeof(val) );
            printf( "son Data received: %d\n", val );
            ++val;
            write( fd[1], &val, sizeof(val) );
            printf( "son send received: %d\n", val );
        }
    }
}

输出结果:parent Sending data: 1 
son Data received: 1 
son send received: 2 
parent Data received: 2 
parent Sending data: 3 
son Data received: 3 
son send received: 4 

parent Data received: 4

更多使用实例:《socketpair的用法和理解》https://blog.csdn.net/weixin_40039738/article/details/81095013

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值