• nginx + php + Ajax 学习


    First step nginx和php的配置和启动

    1.下载 nginx 和 php

    2.nginx 配置与启动
    打开nginx.conf文件

      server {
            listen       2333;//可以调整接口为2333(要确保未被占用)
            server_name  localhost;
            location / {
                root   C:\Users\zhongzero\Desktop\interaction;//可以修改自己网站根目录的绝对路径
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
            location ~ \.php$ {
               root           C:\Users\zhongzero\Desktop\interaction;
               fastcgi_pass   127.0.0.1:9020;//php端口(要确保未被占用)
               fastcgi_index  index.php;
               fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
               include        fastcgi_params;
            }
      }
    

    注:

    netstat -aon|findstr "80"
      查看:80接口是否被占用(因为nginx默认要占据:80接口)
      (-a = -all)(-o 显示拥有的与每个连接关联的进程 ID)(-n以数字形式显示地址和端口号)(findstr "80"表示所有包含80这个字符串的信息)
      若是发现被占用,通过上述命令可知占用:80接口的进程ID
    
    tasklist|findstr "xxx” 查看该ID是哪个进程
    

    启动nginx

    ./nginx.exe
    

    nginx可在后端运行(即可以直接关闭运行它的命令行)

    如要关闭nginx,找到相应进程kill(任务管理器/命令行 taskkill /pid xxxx -f) or 输入命令 .\nginx.exe -s quit

    3.php配置与启动
    把php.ini-development文件复制到php.ini
    搜索 extension_dir,修改:

     On Windows
    extension_dir="./ext"  (记得把左边的注释符号';'删除)
    

    搜索cgi.fix_pathinfo 修改:

    cgi.fix_pathinfo=1
    

    搜索extension=sockets 修改:

    extension=sockets (把左边的注释符号';'删除)
    

    启动php

    ./php-cgi.exe -b 127.0.0.1:9020 -c php.ini  (端口要和nginx中写的对上)
    

    (不能把运行它的命令行关掉)

    1. 测试是否成功
      在网页根目录下添加 phpinfo.php
    <?php 
        phpinfo();
    ?>
    

    在浏览器中打开localhost:2333/phpinfo.php,查看是否能成功访问

    Step2 php语法学习 + Get/Post使用

    1.php基础语法

    <!-- PHP文件 包含 HTML标签 和 PHP脚本代码 -->
    <html>
    <body>
    	<h1>My first PHP page</h1>
    	<?php
    		$x=5;//$表示为变量
    		$y=6;
    		$z=$x+$y;
    		echo $z,"</br>";//echo输出,输出多个用","间隔,双引号表示直接输出字符串(相当于输出成一个html文件,最后由浏览器解析)
    		$Array=array("apple","banana","orange");//数组定义
    		foreach($Array as $x){//遍历数组
    			echo "Key=",$x,"</br>";//echo输出
    		}
    	?>
    </body>
    

    2.Get/Post在前后端(html,php)的使用

    前端(test.html,用表单传递)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>HTML form表单演示</title>
    </head>
    <body>
        <form action="./userinfo.php" method="post">//用get则改成get(不区分大小写);传递数据给网站根目录下的useinfo.php,提交表单后会自动跳转到userinfo.php
            <!-- 文本输入框控件 -->
            <label>用户名: </label><input name="username" type="text"><br>
    
            <!-- 密码框控件 -->
            <label>密&emsp;码: </label><input name="password" type="password"><br>
    
            <!-- 下拉菜单控件 -->
            <label>性&emsp;别:</label>
            <select name="sex">
                <option value="1">男</option>
                <option value="2">女</option>
                <option value="3">未知</option>
            </select>
            <br>
    
            <!-- 复选框控件 -->
            <label>爱&emsp;好:</label>
            <input type="checkbox" name="hobby" value="1">听音乐
            <input type="checkbox" name="hobby" value="2">看电影
            <input type="checkbox" name="hobby" value="3">打游戏
            <br>
    
            <!-- 单选按钮控件 -->
            <label>学&emsp;历:</label>
            <input type="radio" name="education" value="1">小学
            <input type="radio" name="education" value="2">中学
            <input type="radio" name="education" value="3">本科
            <input type="radio" name="education" value="4">硕士
            <input type="radio" name="education" value="5">博士
            <br>
    
            <!-- 按钮 -->
            <input type="submit" value="提 交">&emsp;&emsp;
            <input type="reset" value="重 置">
        </form>
    </body>
    </html>
    

    后端(userinfo.php)

    欢迎<?php echo $_POST["username"]; ?>!<br>   <!-- 用get则改成get(区分大小写) -->
    <!-- 下拉菜单、复选框、单选按钮等表单数据在后端读取的方法详见https://m.runoob.com/php/php-forms.html -->
    

    打开 http://localhost:2333/d.html
    在test.html中的表单提交后,会自动跳转到 http://localhost:2333/userinfo.php

    3.Get/Post的区别
    1.post发送的数据对任何人都是不可见的,get是可见的
    以上为例
    若用post提交,会跳转到 http://localhost:2333/userinfo.php
    若用get提交,会跳转形如 http://localhost:2333/userinfo.php?username=zhongzero&password=123456&sex=1&hobby=1&hobby=3&education=1
    post的好处在于安全,但get更快一些,而且由于get可见的特性,get提交后跳转的网址可以被保存在收藏夹中
    2.get提交的数据大小受限
    post不受限(虽然默认为8MB,不过可以随便调)

    Step3 Ajax

    Ajax 全称 Asynchronous(异步) JavaScript and XML
    AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
    AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
    传统的网页(不使用 AJAX)如果需要更新内容,必须重载整个页面。(如上的基于表单的测试)
    更多可参考:https://www.runoob.com/ajax/ajax-tutorial.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <script>
    function loadXMLDoc()
    {
        var xmlhttp;//定义变量
        if (window.XMLHttpRequest)
        {
          // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
          xmlhttp=new XMLHttpRequest();//创建一个XMLHttpRequest对象
        }
        else
        {
          // IE6, IE5 浏览器执行代码
          xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");//IE5,IE6不支持XMLHttpRequest,得使用这种方法
        }
        xmlhttp.onreadystatechange=function()//每当 readyState 属性改变时,就会调用该函数
        {
            if (xmlhttp.readyState==4 && xmlhttp.status==200){//表示已成功获取到数据
                //readyState表示请求状态(0:未初始化,1:服务器连接已建立,2:请求已接收,3:请求处理中,4:请求已完成,且响应已就绪)
                //status (200:OK,404:未找到页面)
                document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
                //document.getElementById("myDiv")表示找到第一个id为myDiv的标签的引用
                //这里做到了把找到的标签的内部html代码改成xmlhttp中获得到的
                //xmlhttp.responseText返回的是string类型
                //xmlhttp.responseXML返回的是xml类型,此时还需要对获取的文件进行进一步解析
          }
        }
        //以下为POST请求方式
        xmlhttp.open("POST","./userinfo.php",true);
        //请求方式,请求地址,是否开启异步
        //默认请开启异步
        xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        //设置html header
        //html header一般作用是 告诉电脑应该用什么语言、什么规范之类的
        //这里的参数表示的是允许传递变量中蕴含的内容(大概)
        //更多header信息详见 https://kb.cnblogs.com/page/92320/
        
        // xmlhttp.send("username=zhongzero&password=123456");
        var username=document.getElementById("username").value;
        var password=document.getElementById("password").value;
        xmlhttp.send("username="+username+"&password="+password);
        //Post在此传递参数
        
        /*
        //以下为Get请求方式
        // xmlhttp.open("GET","./userinfo.php?username=zhongzero&password=123456",true);
        var username=document.getElementById("username").value;
        var password=document.getElementById("password").value;
        xmlhttp.open("GET","./userinfo.php?username="+username+"&password="+password,true);
        xmlhttp.send();
        */
    }
    </script>
    </head>
    <body>
    
    <h2>AJAX</h2>
    <div>
        username
        <input type="text" id="username">
    </div>
    <div>
        password
        <input type="password" id="password">
    </div>
    <button type="button" onclick="loadXMLDoc()">请求数据</button>    <!-- 每次onclick时执行loadXMLDoc() js函数 -->
    <div id="myDiv"></div>     <!-- 一开始其中内容为空,点击上述按钮后,通过id索引找到此处位置,可将其中代码进行修改 -->
     
    
    </body>
    </html>
    

    Step4 socket

    通过socket使不同进程(php和C++)之间交互数据
    php文件

    <!-- 注意要改php.ini 中的extension socket -->
    <?php
    	
    	$sss=$_POST["username"];
    	$socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//创建一个socket
    	socket_connect($socket,'127.0.0.1',9030);//开始一个socket连接
    	socket_write($socket,$sss);//写数据到socket缓存
    	$res=socket_read($socket,300000);//300000为读取数据字节上界
    	echo $res;
    	// if($res=="-1")echo $res;
    	// else {
    
    	// }
    ?>
    

    C++文件(Linux系统下)

    #include<iostream>
    #include<cstring>
    #include <netinet/in.h>
    #include <sys/socket.h>
    string Solve(string order){
    }
    int main() {
    	// 创建套接字
    	int slisten = socket(AF_INET, SOCK_STREAM, 0);
    	//用来指定套接字使用的地址格式,通常使用AF_INET
    	//指定套接字的类型,此处用的是SOCK_DGRAM,表示为udp不可靠传输
    	//配合type参数使用,指定使用的协议类型(当指定套接字类型后,可以设置为0,因为默认为UDP或TCP)
    	
    	// 填充sockaddr_in结构 ,是个结构体
    	/* struct sockaddr_in {
    
    	short sin_family;  //地址族(指定地址格式) ,设为AF_INET
    	u_short	sin_port; //端口号
    	struct in_addr sin_addr; //IP地址
    	char sin_zero[8]; //空子节,设为空
    	} */
    	sockaddr_in sin;
    	sin.sin_family = AF_INET;
    	sin.sin_port = htons(9030);//端口号(1024 ~ 49151)
    	sin.sin_addr.s_addr = htonl(INADDR_ANY);
    
    	// 绑定这个套节字到一个本地地址
    	if (bind(slisten, (struct sockaddr *)&sin, sizeof(sin)) == -1){
    		printf("Failed bind()\n");
    		return 0;
    	}
    
    	// 进入监听模式
    	//5指的是,监听队列中允许保持的尚未处理的最大连接数
    	if (listen(slisten, 5) == -1) {
    		printf("Failed listen()\n");
    		return 0;
    	}
    
    	int sclient;
    	sockaddr_in client_add;
    	socklen_t naddrlen = sizeof(client_add);
    	char data[100000];
    
    	while (1) {
    		memset(data, 0, sizeof(data));
    		// 接受一个新连接
    		//(struct sockaddr *)&client_add 一个指向sockaddr_in结构的指针,用于获取对方地址
    		sclient = accept(slisten, (struct sockaddr *)&client_add, &naddrlen);
    		if (sclient == -1) {printf("Failed accept()");continue;}
    		//从客户端接收数据
    		recv(sclient, data, 100000, 0);
    		std::cout << "接受到一个连接:"<<data<<endl;
    		//处理数据
    		std::string result = Solve(data);
    		// 向客户端发送数据
    		send(sclient, result.c_str(), result.length(), 0);
    	}
    	return 0;
    }
    

    C++文件(Windows系统下)

    #include <stdio.h> 
    #include <iostream>
    #include <winsock2.h> 
    #include <stdlib.h>  
    #include <conio.h>  
    #include <stdio.h>
    using namespace std;
    class CInitSock{
    public:
    	CInitSock(BYTE minorVer=2, BYTE majorVer=2){
    		// 初始化WS2_32.dll
    		WSADATA wsaData;
    		WORD sockVersion=MAKEWORD(minorVer, majorVer);
    		if(::WSAStartup(sockVersion,&wsaData)!=0){exit(0);}
    	}
    	~CInitSock(){::WSACleanup();}
    };
    CInitSock initSock;//初始化Winsock库
    int main(){
    	system("chcp 65001");//更改格式,防止出现中文乱码
    	// 创建套接字
    	SOCKET sListen=::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    	//用来指定套接字使用的地址格式,通常使用AF_INET
    	//指定套接字的类型,此处用的是SOCK_DGRAM,表示为udp不可靠传输
    	//配合type参数使用,指定使用的协议类型(当指定套接字类型后,可以设置为0,因为默认为UDP或TCP)
    	if(sListen==INVALID_SOCKET){
    		printf("Failed socket()\n");
    		return 0;
    	}
    
    	// 填充sockaddr_in结构 ,是个结构体
    	/* struct sockaddr_in {
    
    	short sin_family;  //地址族(指定地址格式) ,设为AF_INET
    	u_short	sin_port; //端口号
    	struct in_addr sin_addr; //IP地址
    	char sin_zero[8]; //空子节,设为空
    	} */
    
    	sockaddr_in sin;
    	sin.sin_family=AF_INET;
    	sin.sin_port=htons(9030);//端口号(1024 ~ 49151)
    	sin.sin_addr.S_un.S_addr=INADDR_ANY;
    
    	// 绑定这个套节字到一个本地地址
    	if(::bind(sListen,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR){
    		printf("Failed bind()\n");
    		return 0;
    	}
    
    	// 进入监听模式
    	//2指的是,监听队列中允许保持的尚未处理的最大连接数
    	if(::listen(sListen,2)==SOCKET_ERROR){
    		printf("Failed listen()\n");
    		return 0;
    	}
    
    	while(TRUE){
    		sockaddr_in remoteAddr;
    		int nAddrLen=sizeof(remoteAddr);
    		SOCKET sClient=0;
    		// 接受一个新连接
    		//((SOCKADDR*)&remoteAddr)一个指向sockaddr_in结构的指针,用于获取对方地址
    		sClient=::accept(sListen,(SOCKADDR*)&remoteAddr, &nAddrLen);
    		if(sClient==INVALID_SOCKET){printf("Failed accept()");continue;}
    		printf("接受到一个连接:%s\r\n",inet_ntoa(remoteAddr.sin_addr));
    		//从客户端接收数据
    		char data[300];
    		int nRecv=::recv(sClient,data,300,0);//从socket缓存读取数据,300为接收数据字节上限,返回值为接收数据字节数
    		if(nRecv>0){
    			data[nRecv]='\0';
    			printf("接收到数据:%s\n",data);
    		}
    		/*
    		...
    		处理数据
    		*/
    		// 向客户端发送数据
    		::send(sClient,data,strlen(data),0);
    		// 关闭同客户端的连接
    		::closesocket(sClient);
    	}
    	// // 关闭监听套节字
    	// ::closesocket(sListen);
    	return 0;
    } 
    

    注意C++文件在编译时(Windows系统下)加上 -lwsock32 指令,表示 链接到WS2_32.lib动态库,其是Windows Sockets应用程序接口

    由于Windows系统在编码等方面存在诸多问题,所以建议还是在linux系统下编译

    总体概括为:
    C++文件中创建一个socket,并找一个端口进行监听(listen);
    php文件中创建一个socket,并对该端口开始一个socket连接(connect);
    C++文件中的socket接受该socket连接(accept);
    php文件把数据写到socket缓存中(write);
    C++文件从socket缓存处读取文件(recv);
    C++文件把数据发出(send);
    php文件读取数据(read);

    详见 https://blog.csdn.net/dlutbrucezhang/article/details/8577810https://blog.csdn.net/weixin_35253106/article/details/115316408

    Step5 json格式传递

    C++通过socket传回字符串到php文件
    考虑如何将php文件中得到的字符串转化成json格式
    php

    $tmp_arr=explode(" ",$res);//按" "将字符串res分离,放入数组tmp_arr中
    $arr=array('startstation'=>$tmp_arr[0],'startdate'=>$tmp_arr[1],'starttime'=>$tmp_arr[2],'endstation'=>$tmp_arr[4],'enddate'=>$tmp_arr[5],'endtime'=>$tmp_arr[6]);
    echo json_encode($arr);//将数组编码成json格式传回
    

    上述js中接收到的是json格式的字符串
    考虑如何在js中把json格式的字符串转成json类型并考虑进行字符串输出

    var str=xmlhttp.responseText;
    var data=eval("("+str+")");//eval函数将字符串类型的json数据转化成json类型
    var ans=JSON.stringify(data.startstation);//JSON.stringify()可将json类型转化成字符串类型的json数据
    ans=ans.substring(1,ans.length-1);//去除头尾两个双引号
    document.getElementById("ShowPassword").innerHTML=ans;//在具体位置显示
    

    总结

    通过上述操作,我们便可实现
    前端(网页 .html/css/js)——网页服务器(后端 .php)——逻辑服务器(后端 C++)——数据库(后端)

    首先通过 nginx开放端口,我们可以实现html/js文件与php文件的数据交互,再使用Ajax的方法,我们可以实现 在不重新加载整个页面的前提下更改页面信息
    接着通过socket,我们可以实现php文件和C++的数据交互
    而最后的数据库和C++可以手写B+tree作为数据库进行交互

  • 相关阅读:
    [C#]生成缩略图
    [C#]原来DataTable的Distinct竟如此简单!
    [C#] UTF8 ENCODING=QUOTEDPRINTABLE 的解码和编码
    ASP.NET将文件写到另一服务器
    生成machineKey密钥
    Docx转Doc操作(c#)
    Linq学习知识摘记
    HTTP 状态代码
    文件与流相关code
    Web文件的ContentType类型大全
  • 原文地址:https://www.cnblogs.com/zhongzero/p/16176911.html
Copyright © 2020-2023  润新知