进程间通信-unix套接字

概括

UNIX域套接字用于在同一台机器上运行的进程之间的通信。虽然因特网域套接字可用于同一目的,但UNIX域套接字的效率更高。UNIX域套接字仅仅复制数据;它们并不执行协议处理,不需要添加或删除网络报头,无需计算检验和,不要产生顺序号,无需发送确认报文。

套接字的属性

套接字的特性由3个属性确定,它们分别是:域、类型和协议。

套接字的域

它指定套接字通信中使用的网络介质,最常见的套接字域是AF_INET,它指的是Internet网络。当客户使用套接字进行跨网络的连接时,它就需要用到服务器计算机的IP地址和端口来指定一台联网机器上的某个特定服务,所以在使用socket作为通信的终点,服务器应用程序必须在开始通信之前绑定一个端口,服务器在指定的端口等待客户的连接。另一个域AF_UNIX表示UNIX文件系统,它就是文件输入/输出,而它的地址就是文件名。

套接字类型

因特网提供了两种通信机制:流(stream)和数据报(datagram),因而套接字的类型也就分为流套接字和数据报套接字。这里主要讲流套接字。
流套接字由类型SOCK_STREAM指定,它们是在AF_INET域中通过TCP/IP连接实现,同时也是AF_UNIX中常用的套接字类型。流套接字提供的是一个有序、可靠、双向字节流的连接,因此发送的数据可以确保不会丢失、重复或乱序到达,而且它还有一定的出错后重新发送的机制。
与流套接字相对的是由类型SOCK_DGRAM指定的数据报套接字,它不需要建立连接和维持一个连接,它们在AF_INET中通常是通过UDP/IP协议实现的。它对可以发送的数据的长度有限制,数据报作为一个单独的网络消息被传输,它可能会丢失、复制或错乱到达,UDP不是一个可靠的协议,但是它的速度比较高,因为它并一需要总是要建立和维持一个连接。

套接字协议

只要底层的传输机制允许不止一个协议来提供要求的套接字类型,我们就可以为套接字选择一个特定的协议。通常只需要使用默认值。

TCP和UDP套接字类型

TCP 是一种面向连接的字节流套接字,所以服务端需要通过 listen() 转变为被动 socket,通过 accept() 等待连接。

而对于 UDP 来说,就比较简单了,因为它是一种无连接的数据报套接字,实际上,客户/服务端的概念也弱化了。

上PHP代码

无命名套接字

用于有血缘的进程间通信

<?php
$fd = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);

$pid = pcntl_fork();
if($pid == 0){
    while (1){
        $data = fread($fd[0], 128);
        if($data){
            fprintf(STDOUT, "读取到了:%s \n", $data);
        }
    }
    exit();
}

while (1){
    fwrite($fd[1],'hello-'.time(), 128);
    sleep(1);
}

命名TCP套接字

服务端

<?php
// 创建
$socket = socket_create(AF_UNIX, SOCK_STREAM, IPPROTO_IP);
// 绑定
socket_bind($socket, 'unix_socket_c');
// 监听
socket_listen($socket, 5);
// 等待连接-阻塞
$connect = socket_accept($socket);

if($connect){
    while (1){
        $data = socket_read($connect, 1024);
        if($data){
            fprintf(STDOUT, "接受到 %s \n", $data);
            if(strncasecmp($data, "exit", 4) == 0){
                socket_write($connect, "exit", 1024);
                break;
            }
            else{
                socket_write($connect, "已收到" . $data, 1024);
            }
        }
    }
}

// 关闭连接
socket_close($connect);
// 关闭监听
socket_close($socket);

客户端

<?php
// 创建
$socket = socket_create(AF_UNIX, SOCK_STREAM, IPPROTO_IP);
// 连接
$connect = socket_connect($socket,'unix_socket_c');

if($connect){
    fprintf(STDOUT, "连接成功 \n");
    //子进程用来接收发送结果
    $pid = pcntl_fork();
    if($pid == 0){
        while (1){
            $data = socket_read($socket, 1024);
            if($data){
                fprintf(STDOUT, "--%s \n", $data);
                if(strncasecmp($data, "exit", 4) == 0){
                    fprintf(STDOUT, "子进程退出 \n");
                    break;
                }
            }
        }
        exit();
    }
    while (1){
        $data = fread(STDIN, 1024);
        if($data){
            socket_send($socket, $data, strlen($data), 0);
            if(strncasecmp($data, "exit", 4) == 0){
                fprintf(STDOUT, "父进程退出 \n");
                break;
            }
        }
    }
}
$pid = pcntl_wait($status);
if($status){
    fprintf(STDOUT, "子进程退出 %d \n", $pid);
}

UDP命名套接字

服务端

<?php
// 创建
$socket = socket_create(AF_UNIX, SOCK_DGRAM, IPPROTO_IP);
// 绑定
socket_bind($socket, 'unix_socket_x');

while (1){
    $len = socket_recvfrom($socket,$data, 1024, 0, $file);
    if($len){
        fprintf(STDOUT, "接收到 %s \n", $data);
    }
}

客户端

<?php
// 创建
$socket = socket_create(AF_UNIX, SOCK_DGRAM, IPPROTO_IP);

while (1){
    $data = fread(STDIN, 1024);
    socket_sendto($socket,$data, strlen($data), 0, 'unix_socket_x');
    fprintf(STDOUT, "发送:%s", $data);
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇