php-socket编程代码实例

来源:互联网 发布:seo why 编辑:程序博客网 时间:2024/06/05 21:00

  最近在看计算机网络,对socket原语有了一个新的认识,发现php也可以支持socket编程,而且非常方便。大家可以查看php手册,里面有很全面的socket操作函数。

然后我就写了一个简单的实例,大家可以借鉴一下。

首先说明一下,如果大家对socket不是很了解的话,那么先补充一下socket的知识。

socket可以直接和传输层的tcp协议交互,然后实现端对端的数据传输,socket的存在其实是一对,服务器端对客户端。

所以我们要实现的代码也是首先要实现服务器端,然后再实现客户端,先启动服务器端,以一个进程的形式在等待客户端调用,一旦客服端发起连接请求,服务器端就会和客户端创建一个连接,然后开始和客户端进行数据传输。

原语含义SOCKET创建一个新的通讯端点BIND将套接字与一个本地地址关联LISTEN声明愿意接受连接;给出队列长度ACCEPT被动创建一个入境连接CONNECT主动创建一个连接SEND通过连接发送一些数据RECEIVE从连接上接收一些数据CLOSE释放链接下面是php服务器端的代码:server.php

 #!/usr/bin/php -q    <?php    require './socket.php';    $error_code = socket_server();

客户端代码:client.php

 <?php                                                                                                                      require './socket.php';    $server_ip      = LOCALHOST_IP;    $socket_port    = DEFAULT_SOCKET_PORT;    $data           = 'hello world!';    socket_client($server_ip, $socket_port, $data);
公用脚本(这里面是对服务器端和客户端具体实现):socket.php
<?php                                                                                                                      set_time_limit(0);    define('LOCALHOST_IP',                  '127.0.0.1');    define('DEFAULT_SOCKET_PORT',           2407);    //允许同时连接到服务器端的客户机数目    define('MAX_CONNECT_NUM',               5);    define('DATA_LENGTH',                   1024);    //定义服务器端错误code    define('SOCKET_CREATE_ERROR',           '44001');    define('SOCKET_SETBLOCK_ERROR',         '44002');    define('SOCKET_BIND_ERROR',             '44003');    define('SOCKET_LISTEN_ERROR',           '44004');    define('SOCKET_ACCEPT_ERROR',           '44005');    define('SOCKET_READ_DATA_ERROR',        '44005');    define('SOCKET_WRITE_ERROR',            '44006');    //定义客户端错误code    define('SOCKET_CLIENT_CREATE_FAILED',   '55001');    define('SOCKET_CLIENT_CONNECT_FAILED',  '55002');    define('SOCKET_CLIENT_WRTIE_ERROR',     '55003');        /**     * 启用socket服务器端方法     * @param:$host string 服务器端地址 default localhost     * @param:$port int 服务器端口地址 default 2406     * @param:$block bool 设置阻塞模式,true:阻塞 false:非阻塞 default true     * @param:$error string 错误信息     */     function socket_server($host = LOCALHOST_IP, $port = DEFAULT_SOCKET_PORT, $block = true,         $max_connect = MAX_CONNECT_NUM, &$error = '') {        //创建一个soket通讯端点        if ( !($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) ) {            $error = "socket端点创建失败:" . get_socket_last_err();            return SOCKET_CREATE_ERROR;        }        if ( $block ) $block_ret = socket_set_block($socket);        else $block_ret = socket_set_nonblock($socket);        if ( !$block_ret ) {            $error = '阻塞模式设置失败:' . get_socket_last_err();            return SOCKET_SETBLOCK_ERROR;        }        //将套接字和服务器地址绑定        if ( !socket_bind($socket, $host, $port) ) {            $error = "绑定服务器地址失败:" . get_socket_last_err();            return SOCKET_BIND_ERROR;        }        //声明自己愿意接受连接,给出队列长度,同时可以允许多少个客户端连接到服务器        if ( !socket_listen($socket, $max_connect) ) {            $error = "服务器监听失败" . get_socket_last_err();            return SOCKET_LISTEN_ERROR;        }        $curr_buff = '';        $client_id = 0;        while ( true ) {            //被动创建一个入境连接            if ( !($msg_socket = socket_accept($socket)) ) {                $error = "创建入境连接失败" . get_socket_last_err();                return SOCKET_ACCEPT_ERROR;            }            //从连接开始接收数据            $buf = socket_read($msg_socket, DATA_LENGTH, PHP_BINARY_READ);            if ( false === $buf ) {                $error = "读取数据失败" . get_socket_last_err();                return SOCKET_READ_DATA_ERROR;            }            $client_id ++;            if ( $buf == "\r\n" ) {                if ( $curr_buff == 'quit' ) {                    $error = "Client #" . $client_id . ":Disconnect\n";                }                if ( $curr_buff == 'shutdown' ) {                    socket_close($msg_socket);                }            }            $msg = "Received msg was:$buf \n";            //error_log(date("Y-m-d H:i:s") . "\t" . $msg, 3, "/tmp/log");            if ( !socket_write($msg_socket, $msg, strlen($msg)) ) {                $error = "write failed reason:" . get_socket_last_err();                return SOCKET_WRITE_ERROR;            }            socket_close($msg_socket);        }    }    /**     * socket客户端方法      * @param:$host string 服务器端地址 default localhost     * @param:$port int 服务器端口地址 default 2406     * @param:$data mixed 要发送给服务器端的数据     * @param:$error string 错误信息     */    function socket_client($host = LOCALHOST_IP, $port = DEFAULT_SOCKET_PORT, $data = '', &$error = '') {        //创建客户端socket通讯端点        if ( !($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) ) {            $error = "socket端点创建失败:" . get_socket_last_err();                                                                    return SOCKET_CLIENT_CREATE_FAILED;        }        if ( !socket_connect($socket, LOCALHOST_IP, DEFAULT_SOCKET_PORT) ) {            $error = "连接socket服务器失败:" . get_socket_last_err();            return SOCKET_CLIENT_CONNECT_FAILED;        }        if ( !socket_write($socket, $data) ) {            $error = "数据发送失败" . get_socket_last_err();            return SOCKET_CLIENT_WRTIE_ERROR;        }        while ($buff = @socket_read($socket, DATA_LENGTH, PHP_NORMAL_READ) ) {            echo ("Respones was:" . $buff . "\n");        }        socket_close($socket);    }     /**     * 获取socket执行的最后一条错误     */    function get_socket_last_err() {        $error = socket_strerror(socket_last_error()) . "\n";    }
把三个文件放到相同的目录下,然后php cli方式运行server.php以进程的方式挂载起来:php server.php &之后就可以运行client.php,也用cli方式运行:php client.php就可以看到hello world!,这说明客户端已经把data数据发送给服务器端,并且服务器端有做了简单的处理返回给了客户端。
0 0
原创粉丝点击