不会的要多查多问,不然不会的永远不会,哪怕你离会就差了那么一点点
						
					
		
 Websocket通信实例,配合后端php
		
		
		[
 2016/09/27 21:14 | by 刘新修 ]
		
	
 2016/09/27 21:14 | by 刘新修 ]
		本站测试实例访问地址: http://code.liuxinxiu.com/php/Interface/html/WebSocket.html
XML/HTML代码
- <!DOCTYPE html>
 - <html>
 - <head>
 - <title>chatdemo</title>
 - <meta charset="utf-8">
 - <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
 - <link href="http://code.liuxinxiu.com/lib/bootstrap/3.3.2/bootstrap.min.css" rel="stylesheet">
 - <style type="text/css">
 - <!--
 - html, body {
 - min-height: 100%; }
 - body {
 - margin: 0;
 - padding: 0;
 - width: 100%;
 - font-family: "Microsoft Yahei",sans-serif, Arial; }
 - .container {
 - text-align: center; }
 - .title {
 - font-size: 16px;
 - color: rgba(0, 0, 0, 0.3);
 - position: fixed;
 - z-index:1000;
 - line-height: 30px;
 - height: 30px;
 - left: 0px;
 - right: 0px;
 - background-color: white; }
 - .content {
 - background-color: #f1f1f1;
 - border-top-left-radius: 6px;
 - border-top-right-radius: 6px;
 - margin-top: 30px; }
 - .content .show-area {
 - text-align: left;
 - padding-top: 8px;
 - padding-bottom: 168px; }
 - .content .show-area .message {
 - width: 70%;
 - padding: 5px;
 - word-wrap: break-word;
 - word-break: normal; }
 - .content .write-area {
 - position: fixed;
 - bottom: 0px;
 - right: 0px;
 - left: 0px;
 - background-color: #f1f1f1;
 - z-index: 10;
 - width: 100%;
 - height: 160px;
 - border-top: 1px solid #d8d8d8; }
 - .content .write-area .send {
 - position: relative;
 - top: -28px;
 - height: 28px;
 - border-top-left-radius: 55px;
 - border-top-right-radius: 55px; }
 - .content .write-area #name{
 - position: relative;
 - top: -20px;
 - line-height: 28px;
 - font-size: 13px; }
 - -->
 - </style>
 - </head>
 - <body>
 - <div class="container">
 - <div class="title">简易聊天demo</div>
 - <div class="content">
 - <div class="show-area"></div>
 - <div class="write-area">
 - <div><button class="btn btn-default send" >发送</button></div>
 - <div><input name="name" id="name" type="text" placeholder="input your name"></div>
 - <div>
 - <textarea name="message" id="message" cols="38" rows="4" placeholder="input your message..."></textarea>
 - </div>
 - </div>
 - </div>
 - </div>
 - <script src="http://code.liuxinxiu.com/lib/jquery/1.9.1/jquery.min.js"></script>
 - <script src="http://code.liuxinxiu.com/lib/bootstrap/3.3.2/bootstrap.min.js"></script>
 - <script>
 - $(function(){
 - var wsurl='ws://code.liuxinxiu.com:9090/php/webSocket/server.php';
 - var websocket;
 - var i = 0;
 - /******** 判断是否有webSocket对象 *******/
 - if(window.WebSocket){
 - websocket=new WebSocket(wsurl);
 - /******** 连接建立||发起webSocket连接 ********/
 - websocket.onopen = function(evevt){
 - console.log("Connected to WebSocket server.");
 - /******** 监听ready状态码 ********/
 - console.log('websocket.readyState:'+websocket.readyState);
 - /*********************************************************
 - 值为0值表示该连接尚未建立
 - 值为1表示连接建立和沟通是可能的
 - 值为2表示连接是通过将结束握手
 - 值为3表示连接已关闭或无法打开
 - *********************************************************/
 - /******** 判断状态码为1则连接成功即可正常通信********/
 - if(websocket.readyState==1){
 - $('.show-area').append('<p class="bg-info message"><i class="glyphicon glyphicon-info-sign"></i>Connected to WebSocket server!</p>');
 - }
 - }
 - //收到消息
 - websocket.onmessage = function(event) {
 - var msg = JSON.parse(event.data); //解析收到的json消息数据
 - console.log("\n--->>message:\n"+event.data);
 - var type = msg.type; // 消息类型
 - var umsg = msg.message; //消息文本
 - var uname = msg.name; //发送人
 - i++;
 - if(type == 'usermsg'){
 - $('.show-area').append('<p class="bg-success message"><i class="glyphicon glyphicon-user"></i><a name="'+i+'"></a><span class="label label-primary">'+uname+' say: </span>'+umsg+'</p>');
 - }
 - if(type == 'system'){
 - $('.show-area').append('<p class="bg-warning message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>'+umsg+'</p>');
 - }
 - $('#message').val('');
 - window.location.hash = '#'+i;
 - }
 - //发生错误
 - websocket.onerror = function(event){
 - i++;
 - console.log("Connected to WebSocket server error");
 - $('.show-area').append('<p class="bg-danger message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>Connect to WebSocket server error.</p>');
 - window.location.hash = '#'+i;
 - }
 - //连接关闭
 - websocket.onclose = function(event){
 - i++;
 - console.log('websocket Connection Closed. ');
 - $('.show-area').append('<p class="bg-warning message"><a name="'+i+'"></a><i class="glyphicon glyphicon-info-sign"></i>websocket Connection Closed.</p>');
 - window.location.hash = '#'+i;
 - }
 - function send(){
 - var name = $('#name').val();
 - var message = $('#message').val();
 - if(!name){
 - alert('请输入用户名!');
 - return false;
 - }
 - if(!message){
 - alert('发送消息不能为空!');
 - return false;
 - }
 - var msg = {
 - message: message,
 - name: name
 - };
 - try{
 - websocket.send(JSON.stringify(msg));
 - } catch(ex) {
 - console.log(ex);
 - }
 - }
 - //按下enter键发送消息
 - $(window).keydown(function(event){
 - if(event.keyCode == 13){
 - console.log('user enter');
 - send();
 - }
 - });
 - //点发送按钮发送消息
 - $('.send').bind('click',function(){
 - send();
 - });
 - }
 - else{
 - alert('该浏览器不支持web socket');
 - }
 - });
 - </script>
 - </body>
 - </html>
 
后端PHP代码部分:
PHP代码
- 2.php code:
 - <?php
 - $host = '127.0.0.1';
 - $port = '9090';
 - $null = NULL;
 - //创建tcp socket
 - $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
 - socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
 - socket_bind($socket, 0, $port);
 - //监听端口
 - socket_listen($socket);
 - //连接的client socket 列表
 - $clients = array($socket);
 - //设置一个死循环,用来监听连接 ,状态
 - while (true) {
 - $changed = $clients;
 - socket_select($changed, $null, $null, 0, 10);
 - //如果有新的连接
 - if (in_array($socket, $changed)) {
 - //接受并加入新的socket连接
 - $socket_new = socket_accept($socket);
 - $clients[] = $socket_new;
 - //通过socket获取数据执行handshake
 - $header = socket_read($socket_new, 1024);
 - perform_handshaking($header, $socket_new, $host, $port);
 - //获取client ip 编码json数据,并发送通知
 - socket_getpeername($socket_new, $ip);
 - $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' connected')));
 - send_message($response);
 - $found_socket = array_search($socket, $changed);
 - unset($changed[$found_socket]);
 - }
 - //轮询 每个client socket 连接
 - foreach ($changed as $changed_socket) {
 - //如果有client数据发送过来
 - while(socket_recv($changed_socket, $buf, 1024, 0) >= 1)
 - {
 - //解码发送过来的数据
 - $received_text = unmask($buf);
 - $tst_msg = json_decode($received_text);
 - $user_name = $tst_msg->name;
 - $user_message = $tst_msg->message;
 - //把消息发送回所有连接的 client 上去
 - $response_text = mask(json_encode(array('type'=>'usermsg', 'name'=>$user_name, 'message'=>$user_message)));
 - send_message($response_text);
 - break 2;
 - }
 - //检查offline的client
 - $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
 - if ($buf === false) {
 - $found_socket = array_search($changed_socket, $clients);
 - socket_getpeername($changed_socket, $ip);
 - unset($clients[$found_socket]);
 - $response = mask(json_encode(array('type'=>'system', 'message'=>$ip.' disconnected')));
 - send_message($response);
 - }
 - }
 - }
 - // 关闭监听的socket
 - socket_close($sock);
 - //发送消息的方法
 - function send_message($msg)
 - {
 - global $clients;
 - foreach($clients as $changed_socket)
 - {
 - @socket_write($changed_socket,$msg,strlen($msg));
 - }
 - return true;
 - }
 - //解码数据
 - function unmask($text) {
 - $length = ord($text[1]) & 127;
 - if($length == 126) {
 - $masks = substr($text, 4, 4);
 - $data = substr($text, 8);
 - }
 - elseif($length == 127) {
 - $masks = substr($text, 10, 4);
 - $data = substr($text, 14);
 - }
 - else {
 - $masks = substr($text, 2, 4);
 - $data = substr($text, 6);
 - }
 - $text = "";
 - for ($i = 0; $i < strlen($data); ++$i) {
 - $text .= $data[$i] ^ $masks[$i%4];
 - }
 - return $text;
 - }
 - //编码数据
 - function mask($text)
 - {
 - $b1 = 0x80 | (0x1 & 0x0f);
 - $length = strlen($text);
 - if($length <= 125)
 - $header = pack('CC', $b1, $length);
 - elseif($length > 125 && $length < 65536)
 - $header = pack('CCn', $b1, 126, $length);
 - elseif($length >= 65536)
 - $header = pack('CCNN', $b1, 127, $length);
 - return $header.$text;
 - }
 - //握手的逻辑
 - function perform_handshaking($receved_header,$client_conn, $host, $port)
 - {
 - $headers = array();
 - $lines = preg_split("/\r\n/", $receved_header);
 - foreach($lines as $line)
 - {
 - $line = chop($line);
 - if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
 - {
 - $headers[$matches[1]] = $matches[2];
 - }
 - }
 - $secKey = $headers['Sec-WebSocket-Key'];
 - $secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
 - $upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
 - "Upgrade: websocket\r\n" .
 - "Connection: Upgrade\r\n" .
 - "WebSocket-Origin: $host\r\n" .
 - "WebSocket-Location: ws://$host:$port/demo/shout.php\r\n".
 - "Sec-WebSocket-Accept:$secAccept\r\n\r\n";
 - socket_write($client_conn,$upgrade,strlen($upgrade));
 - }
 
		
 CORS||跨域资源共享||PHP版本实现
		
		
		[
 2016/09/12 12:15 | by 刘新修 ]
		
	
 2016/09/12 12:15 | by 刘新修 ]
		使用PHP实现CORS 跨域资源共享,可传参origin通过限制,代码如下:
PHP代码
- <?php
 - /******** 定义Response返回header头格式及编码 ********/
 - header('Content-type: application/json; charset=utf-8');
 - /******** 回调参数设置 ********/
 - $param="origin";
 - $origin_URL=$_REQUEST[$param];
 - /******** json_encode 转成=> encode_json *******/
 - function encode_json($str){
 - return urldecode(json_encode(url_encode($str)));
 - }
 - function url_encode($str){
 - if(is_array($str)){
 - foreach($str as $key=>$value){
 - $str[urlencode($key)]=url_encode($value);
 - }
 - }else{
 - $str=urlencode($str);
 - }
 - return $str;
 - }
 - /**************** \/\/反转义范例 ********************/
 - function stripslashes_deep($value){
 - $value=is_array($value)?
 - array_map('stripslashes_deep',$value):
 - stripslashes($value);
 - return $value;
 - }
 - /******************** Example ******************************/
 - $array=array("f\\'oo", "b\\'ar", array("fo\\'o", "b\\'ar"));
 - $array=stripslashes_deep($array);
 - /******************** Output *******************************/
 - //echo encode_json(array('china'=>'钓鱼岛是中国的!','Japan'=>array('name'=>'日本狗!')));
 - /************ 定义Post过来什么数据就返回什么数据 ***********/
 - $res=array(
 - 'status'=>-1,
 - 'name'=>isset($_POST['name'])?$_POST['name']:'',
 - 'gender'=>isset($_POST['gender'])?$_POST['gender']:''
 - );
 - $arr=array(
 - "status"=>1,
 - "url"=>"http://www.liuxinxiu.com/",
 - "dataList"=>array(
 - "siteId"=>"1",
 - "title"=>urldecode('我的博客'),
 - "images"=>"http://192.168.9.100/upload/2015/06/20/moren.gif",
 - "indexNum"=>10,
 - "pageNum"=>"300",
 - "tagNum"=>"20",
 - "linkType"=>"linkTaobao",
 - "publishTime"=>"20:00:00"
 - )
 - );
 - $arr['dataList']['images']="http://www.liuxinxiu.com/upload/2015/06/20/moren.gif";
 - //print_r($arr);
 - /*************** 定义错误信息 ***************/
 - $errStr='{"status":-1,"info":"Request Error"}';
 - $errJson=json_decode($errStr,true); //json_decode转成了array数组
 - //print_r($errJson) //转成了array数组
 - /************** 获取客户端的Origin域名 **************/
 - $origin=isset($_SERVER['HTTP_ORIGIN'])?$_SERVER['HTTP_ORIGIN']:'';
 - /******** 定义符合规则的域名数组 ********/
 - $allow_origin=array(
 - 'http://liuxinxiu.com',
 - 'http://code.liuxinxiu.com',
 - 'http://test.liuxinxiu.com'
 - );
 - /****************** 判断如果有POST过来数据 *********************/
 - if(isset($_POST['name'])&&isset($_POST['gender'])){
 - /********** 只要是POST请求过来无论合法与否都要正常通信 **********/
 - header('Access-Control-Allow-Methods:POST');
 - header('Access-Control-Allow-Headers:x-requested-with,content-type');
 - /******** 匹配客户端域名是否在数组列表中 ******/
 - if(in_array($origin,$allow_origin)){
 - header('Access-Control-Allow-Origin:'.$origin);
 - $res['status']=1;
 - $res['getUser']=$arr;
 - echo json_encode($res);
 - }
 - else if(!in_array($origin,$allow_origin)){
 - /******** 如有设置就取设置URL返回头信息 ********/
 - if(isset($origin_URL)){
 - header('Access-Control-Allow-Origin:'.$origin_URL);
 - $res['status']=1;
 - $res['getUser']=$arr;
 - echo encode_json($res);
 - //echo json_encode("中文", JSON_UNESCAPED_UNICODE);
 - }
 - /******** 如没有设置URL就返回错误信息 ********/
 - else{
 - header('Access-Control-Allow-Origin:'.$origin);
 - $errJson['status']=-1;
 - $errJson['info']="You don't have permission to submit!";
 - echo encode_json($errJson);
 - }
 - }
 - }
 - /************ 没有所匹配的POST提交数据 ***********/
 - else{
 - if($GLOBALS['HTTP_RAW_POST_DATA']){
 - header('Access-Control-Allow-Origin:'.$origin);
 - $errJson['status']=-1;
 - $errJson['info']="Syntax error in parameters or arguments.";
 - echo encode_json($errJson);
 - }
 - else{
 - header("Content-type: text/html; charset=utf-8");
 - echo 'It is forbidden for the URL request!';
 - }
 - }
 - ?>
 
PHP数据提交接口地址 (禁止使用GET访问):http://code.liuxinxiu.com/php/Interface/server.php
配合HTML代码如下:
XML/HTML代码
- <!DOCTYPE html>
 - <html>
 - <head>
 - <meta charset="utf-8"/>
 - <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
 - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
 - <meta name="format-detection"content="telephone=no">
 - <meta name="apple-mobile-web-app-capable" content="yes" />
 - <meta name="apple-mobile-web-app-status-bar-style" content="black" />
 - <style>body,html {background:#fff;font-family: "Lucida Grande",Calibri,Arial;font-size:12pt;color: #333;background: #f8f8f8;text-align:center;}*{margin:0;padding:0;}h1{line-height:1.6em;font-size:24px;text-indent:.5em;padding-top:.6em}i{line-height:2em;font-size:18px;color:#999;}.line{height:10px;border-bottom:1px solid #ccc;font-size:0;overflow:hidden;}</style>
 - <title>跨域测试</title>
 - </head>
 - <body>
 - <h1 id="show"></h1>
 - <input type="button" value="Click me" onclick="msg()" />
 - </body>
 - <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
 - <script type='text/javascript'>
 - /********** 获取URL参数 **********/
 - function getQueryString(name){
 - var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)","i");
 - var r=window.location.search.substr(1).match(reg);
 - if (r!=null) return unescape(r[2]); return null;
 - }
 - /********** 发起Ajax请求 **********/
 - function msg(){
 - /******* 动态切换提交数据 *******/
 - if(_origin){
 - if(_name&&_gender){
 - var data={name:_name,gender:_gender,origin:_origin};
 - }
 - else{
 - var data={name:"xiaoming",gender:"male",origin:_origin};
 - }
 - }
 - else if(_error==null){
 - var data={name:"xiaoming",gender:"male"};
 - }
 - else if(_error){
 - var data={xxx:111};
 - }
 - /******* 动态设置提交URL *******/
 - if(_url){
 - var urlPath=_url;
 - }
 - else{
 - var urlPath='http://code.liuxinxiu.com/php/Interface/server.php';
 - }
 - $.ajax({
 - type:'post',
 - url:urlPath,
 - data:data,
 - cache:false,
 - dataType:'json',
 - success:function(data){
 - if(data.name){
 - document.getElementById("show").innerHTML=data.name+' '+data.gender;
 - }
 - else if(data.status!=1){
 - document.getElementById("show").innerHTML=data.info;
 - }
 - },
 - error:function(){
 - console.log("请求错误//")
 - }
 - });
 - };
 - /***********************************************************************************************
 - $.post("http://www.server.com/server.php",{name:"fdipzone",gender:"male"}).done(function(data){
 - document.getElementById("show").innerHTML=data.name+' '+data.gender;
 - });
 - **********************************************************************************************/
 - </script>
 - </html>
 
HTML访问地址 (测试跨域) ==> http://test1.liuxinxiu.com/php/Interface/html/server.html?n=php
HTML访问地址 (非法参数) ==> http://test1.liuxinxiu.com/php/Interface/html/server.html?error=php
		
 PHP处理HTTP请求的几种方式
		
		
		[
 2016/09/05 17:48 | by 刘新修 ]
		
	
 2016/09/05 17:48 | by 刘新修 ]
		GET,一般是明文的,比如XXX.php?a=1&b=2,这里的a,b就必须用GET方式接收,接收代码如下:
$a = $_GET['a'];
$b = $_GET['b'];
//接收a,b两个变量
POST,一般是隐藏的非明文的,一般表单设置成POST的,接收方式如下:
//比如有个表单,表单中有两个文本框,name 分别是 a,b,那么代码如下:
$a = $_POST['a'];
$b = $_POST['b'];
另外:$_REQUEST,可以同时接收GET、POST的变量,用法如:
$_REQUEST['a'];//接收变量a,a可以是GET的也可以是POST的
另外说说PHP获取POST请求的几种方式:
方法1、最常见的方法是:$_POST['fieldname'];
说明:只能接收Content-Type: application/x-www-form-urlencoded提交的数据
解释:也就是表单POST过来的数据
方法2、file_get_contents(“php://input”);
说明:
允许读取 POST 的原始数据。
和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。
php://input 不能用于 enctype=”multipart/form-data”。
解释:
对于未指定 Content-Type 的POST数据,则可以使用file_get_contents(“php://input”);来获取原始数据。
事实上,用PHP接收POST的任何数据都可以使用本方法。而不用考虑Content-Type,包括二进制文件流也可以。
所以用方法二是最保险的方法。
方法3、$GLOBALS['HTTP_RAW_POST_DATA'];
说明:
总是产生 $HTTP_RAW_POST_DATA 变量包含有原始的 POST 数据。
此变量仅在碰到未识别 MIME 类型的数据时产生。
$HTTP_RAW_POST_DATA 对于 enctype=”multipart/form-data” 表单数据不可用
如果post过来的数据不是PHP能够识别的,可以用 $GLOBALS['HTTP_RAW_POST_DATA']来接收,
比如 text/xml 或者 soap 等等
解释:
$GLOBALS['HTTP_RAW_POST_DATA']存放的是POST过来的原始数据。
$_POST或$_REQUEST存放的是 PHP以key=>value的形式格式化以后的数据。
但$GLOBALS['HTTP_RAW_POST_DATA']中是否保存POST过来的数据取决于centent-Type的设置,即POST数据时 必须显式示指明Content-Type: application/x-www-form-urlencoded,POST的数据才会存放到 $GLOBALS['HTTP_RAW_POST_DATA']中。
变量 $file_name 可以来自上传域或者指定为其他
PHP代码
- <?//方法一:
 - function extend($file_name)
 - {
 - $retval="";
 - $pt=strrpos($file_name, ".");
 - if ($pt) $retval=substr($file_name, $pt+1, strlen($file_name) - $pt);
 - return ($retval);
 - }
 - //方法二(PHP4.03及更高版本)
 - $extend = pathinfo($file_name);
 - $extend = strtolower($extend["extension"]);
 - echo $extend;
 - ?>
 


  
 
 
 
 
 


