专栏首页PHP饭米粒玩转 PHP 网络编程全套之数据接收与发送

玩转 PHP 网络编程全套之数据接收与发送

TCP/IP协议简单扯蛋

它是一个复杂的协议族,但是经过层层封装之后转换为网络数据帧经过网卡发送出去的,当然在发送之前会先发起一次ARP请求查询一下对方的mac物理地址,对方响应后返回以便封装数据传送,一般来说网卡的mac地址有的是写入EEPROM寄存器里存储起来的。 但是它底层网卡驱动要动的事情,那么我们码农只关注一下传输层的TCP/UDP即可,TCP传输层拥有自己的接收与发送缓冲区,而UDP并没有,每次发送数据时,接收端必须立即接受,否则丢包。TCP的发送端与接收端读写次数并不一定相等,这就是字节流的概念,而UDP则是数据报提供不可靠传输。

发送函数API

 socket_write ( resource $socket , string $buffer [, int $length = 0 ] ) : int
 socket_send ( resource $socket , string $buf , int $len , int $flags ) : int
 socket_sendmsg ( resource $socket , array $message [, int $flags = 0 ] ) : int
 socket_sendto( resource $socket , string $buf , int $len , int $flags , string $addr [, int $port = 0 ] ) : int

接收函数API

socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] ) : string
socket_recv ( resource $socket , string &$buf , int $len , int $flags ) : int
socket_recvfrom( resource $socket , string &$buf , int $len , int $flags, string &$name [, int &$port ] ) : int
socket_recvmsg ( resource $socket , array &$message [, int $flags = 0 ] ) : int

TCP字节流的发送与接收

$ip = "0.0.0.0";
$port = $argv[1];
$sockefd = socket_create(AF_INET,SOCK_STREAM,0);
socket_set_option($sockefd,SOL_SOCKET,SO_REUSEPORT,1);
socket_bind($sockefd,$ip,$port);
socket_listen($sockefd,5);

while (1){

    $connfd = socket_accept($sockefd);
    $message = "php is the best language in the world!";
    $remoteIp;
    $remoteAddr;
    //获取socket 文件描述符绑定的端口和地址
    //网卡接收数据时执行的中断函数会根据端口找到对应的文件描符并写入其缓冲区
    //一般带有缓冲的称为IO流【用户空间】
    socket_getpeername($connfd,$remoteIp,$remoteAddr);
    echo "有客户端连接,ip为:".$remoteIp.",端口为:".$remoteAddr.PHP_EOL;
    if ($connfd){
        socket_send($connfd,$message,strlen($message),0);
        while (1){
            $recvMessage = "";
            $recvBytes = socket_recv($connfd,$recvMessage,8192,0);
            if ($recvBytes){
                $sendBytes = socket_sendto($connfd,$recvMessage,$recvBytes,0,$remoteIp,$remoteAddr);
                fprintf(STDOUT,"发送了%d 字节\n",$sendBytes);
            }
        }
    }

}
socket_close($sockefd);
socket_close($connfd);

UDP数据报的发送与接收

UDP SEVER 端

$ip = "0.0.0.0";
$port = $argv[1];
$sockefd = socket_create(AF_INET,SOCK_DGRAM,SOL_UDP);
socket_set_option($sockefd,SOL_SOCKET,SO_REUSEPORT,1);
socket_bind($sockefd,$ip,$port);
function resetClient()
{
//此结构PHP.net手册并没有细说,而是本人通过调试低层内核代码获取以及参考unix API
//大家可以自行参考
    return  [
        'name' =>[],//socket 套接字地址 【有通用地址和专用地址】 协议不同 此参数内容结构不同,后面扯
        'control' =>[],//
        'iov' => [],//数据 可参考 struct iovec
        'flags'=> 0,//接收消息标志位  给0正常就行
        'controllen'=>8192//辅助数据的地址
    ];
}

while(1){
    $client=resetClient(); 
    //在此阻塞SLEEPING
    socket_recvmsg($sockefd,$client,0);
    print_r($client);
    if (isset($client['name']['addr'])){
        socket_sendto($sockefd,"world",5,0,$client['name']['addr'],$client['name']['port']);
    }

    sleep(2);
}

socket_close($sockefd);

UPD CLIENT端

$ip = "127.0.0.1";
$port = $argv[1];
$socketfd = socket_create(AF_INET,SOCK_DGRAM,SOL_UDP);

$msgStruct = [
    'name' =>[
        'addr'=>$ip,
        'port'=>$port
    ],
    'control' =>[],
    'iov' => ["hello,world"],
    'flags'=> 0
];

while (1){
//阻塞读取终端的输入
    $data = fread(STDIN,8192);
    if ($data){
        $recvMsg="";$remoteIp;$remoteAddr;
        socket_sendto($socketfd,$data,strlen($data),0,$ip,$port);
        socket_recvfrom($socketfd,$recvMsg,8192,0,$remoteIp,$remoteAddr);
        fprintf(STDOUT,"ip:%s,port:%d,msg:%s\n",$remoteIp,$remoteAddr,$recvMsg);
    }
}

socket_close($socketfd);

启动后netstat 观察

大家应该看到比较明显的地方是State它并没有显示什么LISTEN

PS:是每次客户端连接端口是系统随机分配的 UDP通信并不像tcp那样连接的操作,而是大家向socket【绑架了ip和端口的文件描述符】进行读写操作完成了所谓的通信。 它的通信只要指定ip,port和数据即可通信,是面向报文并非连接。

本文分享自微信公众号 - PHP饭米粒(phpfamily)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 玩转 PHP 网络编程全套之 libevent 框架首篇

    此框架的扩展是LIBEVENT,php手册地址libevent,该框架了封装I/O事件,定时事件,中断信号事件,内核I/O复用函数支持EPOLL,POLL,SE...

    桶哥
  • 玩转 PHP 网络编程全套阻塞与非阻塞 IO

    上一篇我们撸了不咋样的TCP server,然后还扯了半天的口水,现在呢我们来继续撸客户端

    桶哥
  • 深入剖析 Web 服务器与 PHP 应用的通信机制 - 掌握 CGI 和 FastCGI 协议的运行原理

    身为一名使用 PHP 语言开发后端服务的程序猿,我们每天都和 PHP 以及 Web 服务器产生无数次的亲密接触。得益于它们,我们才能够如此快速的构建出令人陶醉的...

    程序员宝库
  • 基于C#的游戏服务开发(一)

    本篇文章源码下载方法 公众号回复:服务器开发 即可下载。 阅读本系列文章要求: 1.有c#基础并对于网络游戏有一定的了解 2.会unity的基本操作,如果不会请...

    LittleU
  • WebSocket 简介及应用实例

    HTML5 的出现,标志着后 Flash 时代各种现代浏览器的集体爆发,也是谨防 Adobe 一家独大的各家厂商们,历经多年各自为战,想换个活法儿并终于达成一定...

    江米小枣
  • PHP并发IO编程之路

    并发IO问题一直是后端编程中的技术挑战,从最早的同步阻塞Fork进程,到多进程/多线程,到现在的异步IO、协程。PHP程序员因为有强大的LAMP框架,对底层方面...

    后端技术探索
  • PHP并发IO编程之路

    并发IO问题一直是后端编程中的技术挑战,从最早的同步阻塞Fork进程,到多进程/多线程,到现在的异步IO、协程。PHP程序员因为有强大的LAMP框架,对底层方面...

    后端技术探索
  • Redis连接数为何会偏高

    本文介绍了ThinkPHP和YII2两个框架中对于redis的典型使用场景,通过连接数偏高的现象引出了长连接与短连接的概念,并且简单描述了几种网络连接状态,包括...

    needrunning
  • PHP网络技术(四)——Socket简介

    PHP网络技术(四)——Socket简介 (原创内容,转载请注明来源,谢谢) Socket又称为套接字,是操作系统提供的通信层的API,通过套接字,应用程序可以...

    用户1327360

扫码关注云+社区

领取腾讯云代金券