2016-11-04 14:18:58 jacayang 阅读数 4108
  • cURL实战教程

    由King老师精心打造cURL实战课程,由浅入深的讲解了cURL中常见的API,及cURL在实际开发中的应用,实现了模拟登陆、文件上传下载、多线程cURL等。通过cURL可以操作各种网络资源! 山哥出品,必属精品!

    16023 人正在学习 去看看 何山

使用微软的.Net框架的时候很可能会接触到HttWebRequest。使用者在使用的时候有时候会发现这种现象即有时候使用多线程下载速度会变的非常的慢,特别是如果使用多线程去获取响应头部时候。这时候HttpWebRequest 就会让人非常的扫兴。开始的时候使用者很可能认为这是网络连接的原因,但是最近通过和wGet和cUrl两个第三方库进行对比发现这种现象的问题关键并不是网络拥塞原因,而是.Net实现的原因。

为了提高多线程下载的响应和速度有三件事需要注意:
1: 提高 DefaultConnectionLimit
所有的HttpWebRequst类的实例对象都使用ServicePointManager的一些属性,其中一个属性就是”DefaultConnectionLimit”. 默认情况它的值是2,也就是说最多只有两个连接同时建立。如果你想用超过两个以上的多线程进行网络下载的时候这个限制显然成为一个主要障碍,所以为了提高下载响应时间和速度,可以适当增加这个上限值,这个值需要对当前的网络环境有一定了解后来进行设定。

ServicePointManager.DefaultConnectionLimit = connectionLimit;

2:设置正确的代理
另外一个瓶颈就是代理服务器的设置,如果在搜索引擎搜索HttpWebRequest的问题时候,就会一个频繁的问题描述即第一次查询耗费了较长的时间,后面的查询则相对快些。出现这种情况的原因是,使用HttpWebRequest实例的时候,第一次它会去搜索系统代理设置,这种搜索过程需要花费2-8秒钟,有两种方法解决这个问题。
(1)不设置代理
如果不需要代理则直接设置代理为null.这样第一次就不会有系统代理(System-wide)设置查询过程。

HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Proxy = null;

(2)必需代理情况
对于必需代理话而且清楚代理的具体设置的话,则我们手动来设置代理。这样缓慢的搜索代理的过程就不复存在了。

string proxy_url = "proxy.my_proxy.com";
int proxy_port = 8080;
WebProxy proxy = new WebProxy(proxy_url, proxy_port);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Proxy = proxy;

3:关闭Continue(100)
最后一个细节可以介绍几秒钟的时间,更具体的说,对于每个查询需要1/3秒的时间,对于不同数目的查询量(Http连接查询)这个时间也会不同,查询量越大则时间就越多。默认情况下配置一个Continue(100)会被发送在每次查询之前,如果服务器准备处理客户端发送的连接请求即查询的时候,客户端将会接收到来自服务端的响应并开始发送真正的请求。假设当前对服务器有了解并且知道服务器肯定会接受客户端的请求,则可以disable Continue(100)请求。另外,会有一些服务软件本来就不处理Continue(100)的请求,想了解更多上网搜索更多关于100(Continue)的相关内容,或者查询RFC关于Http协议说明
这里写图片描述

ServicePointManager.Expect100Continue = false;

文章转自 原文链接

2016-12-28 17:59:54 hellokandy 阅读数 6501
  • cURL实战教程

    由King老师精心打造cURL实战课程,由浅入深的讲解了cURL中常见的API,及cURL在实际开发中的应用,实现了模拟登陆、文件上传下载、多线程cURL等。通过cURL可以操作各种网络资源! 山哥出品,必属精品!

    16023 人正在学习 去看看 何山

当使用C++想要实现HTTP客户端时,目前通用的做法就是使用libcurl。本文主要分享的是一个基于libcurl的HTTP封装类,其功能包括:同步的(HTTP/HTTPS)GET、POST请求,以及文件下载和进度报告。


头文件代码:

#ifndef __BASE_EASY_CURL_H__
#define __BASE_EASY_CURL_H__
#include <Windows.h>
#include <string>
#include <functional>
using std::string;
//
class IProgressCallback
{
public:
	virtual bool OnProgressCallback(int nValue) = 0;
};

//
class EasyCurl
{
public:
	EasyCurl(void);
	~EasyCurl(void);
	typedef std::tr1::function<void(int)>  ProgressFunction;

public:

	/// @brief		HTTP POST请求
	/// @param[in]	strUrl 输入参数,请求的Url地址,如:https://www.baidu.com
	/// @param[in]	strParam 输入参数,使用格式"name=kandy&pwd=1234"
	/// @param[out]	strResponse 输出参数,返回的内容
	/// @param[in]	pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
	///	@remark		返回是否Post成功
	///	@return		CURLE_OK,成功!其余失败
	int http_post(const string & strUrl, const string & strParam, string & strResponse, const char * pCaPath = NULL);

	/// @brief		HTTPS GET请求
	/// @param[in]	strUrl 输入参数,请求的Url地址,如:https://www.baidu.com
	/// @param[out]	strResponse 输出参数,返回的内容
	/// @param[in]	pCaPath 输入参数,为CA证书的路径.如果输入为NULL,则不验证服务器端证书的有效性.
	///	@remark		返回是否Post成功
	///	@return		CURLE_OK,成功!其余失败
	int http_get(const string & strUrl, string & strResponse, const char * pCaPath = NULL);

	/// @brief		文件下载
	/// @param[in]	url : 要下载文件的url地址
	/// @param[in]	outfilename : 下载文件指定的文件名
	///	@remark		
	///	@return		返回0代表成功
	int download_file(const string & strUrl, const string & strFile);

	/// @brief		进度报告处理
	/// @param[in]	func : 函数地址
	///	@remark		
	///	@return		void
	void set_progress_function(ProgressFunction func);

	/// @brief		进度报告处理
	/// @param[in]	pCallback : 传入的对象
	///	@remark		使用的类继承于IProgressCallback
	///	@return		void
	void set_progress_callback(IProgressCallback *pCallback);
	//	
public:
	void SetDebug(bool bDebug);

protected:
	static int progress_callback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow);

private:
	bool m_bDebug;
	ProgressFunction	m_updateProgress;
	IProgressCallback	*m_pHttpCallback;
};

#endif//__BASE_EASY_CURL_H__

实现代码:

#include "EasyCurl.h"
#include "curl.h"

//#ifdef _DEBUG
//#pragma comment(lib,"libcurl_d.lib")
//#else
//#pragma comment(lib,"libcurl.lib")
//#endif

EasyCurl::EasyCurl(void) 
: m_bDebug(false)
{

}

EasyCurl::~EasyCurl(void)
{

}
//
static int OnDebug(CURL *, curl_infotype itype, char * pData, size_t size, void *)
{
	if(itype == CURLINFO_TEXT)
	{
		printf("[TEXT]%s\n", pData);
	}
	else if(itype == CURLINFO_HEADER_IN)
	{
		printf("[HEADER_IN]%s\n", pData);
	}
	else if(itype == CURLINFO_HEADER_OUT)
	{
		printf("[HEADER_OUT]%s\n", pData);
	}
	else if(itype == CURLINFO_DATA_IN)
	{
		printf("[DATA_IN]%s\n", pData);
	}
	else if(itype == CURLINFO_DATA_OUT)
	{
		printf("[DATA_OUT]%s\n", pData);
	}
	return 0;
}

static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
	string* str = dynamic_cast<string*>((string *)lpVoid);
	if( NULL == str || NULL == buffer )
	{
		return -1;
	}

    char* pData = (char*)buffer;
    str->append(pData, size * nmemb);
	return nmemb;
}
/*  libcurl write callback function */
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) 
{
	size_t written = fwrite(ptr, size, nmemb, stream);
	return written;

	//在这里可以把下载到的数据以追加的方式写入文件
	//FILE* fp = NULL;
	//fopen_s(&fp, "c:\\test.dat", "ab+");//一定要有a, 否则前面写入的内容就会被覆盖了
	//size_t nWrite = fwrite(ptr, nSize, nmemb, fp);
	//fclose(fp);
	//return nWrite;
}

//
int EasyCurl::progress_callback(void *pParam, double dltotal, double dlnow, double ultotal, double ulnow)
{
	EasyCurl* pThis = (EasyCurl*)pParam;
	int nPos = (int)((dlnow / dltotal) * 100);
	//
	if (pThis->m_pHttpCallback)
	{
		pThis->m_pHttpCallback->OnProgressCallback(nPos);
	}
	if (pThis->m_updateProgress)
	{
		pThis->m_updateProgress(nPos);
	}
	return 0;
}
//
int EasyCurl::http_post(const string & strUrl, const string & strParam, string & strResponse, const char * pCaPath)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
	if(m_bDebug)
	{
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
	}
	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
	curl_easy_setopt(curl, CURLOPT_POST, 1);
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strParam.c_str());
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
	if(NULL == pCaPath)
	{
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
	}
	else
	{
		//缺省情况就是PEM,所以无需设置,另外支持DER
		//curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
		curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
	}
	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
	res = curl_easy_perform(curl);
	curl_easy_cleanup(curl);
	return res;
}
//
int EasyCurl::http_get(const string & strUrl, string & strResponse, const char * pCaPath)
{
	CURLcode res;
	CURL* curl = curl_easy_init();
	if(NULL == curl)
	{
		return CURLE_FAILED_INIT;
	}
	if(m_bDebug)
	{
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
	}
	curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&strResponse);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
	if(NULL == pCaPath)
	{
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);//设定为不验证证书和HOST
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
	}
	else
	{
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
		curl_easy_setopt(curl, CURLOPT_CAINFO, pCaPath);
	}
	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 3);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, 3);
	res = curl_easy_perform(curl);
	curl_easy_cleanup(curl);
	return res;
}
//
int EasyCurl::download_file(const string & strUrl, const string & strFile)
{
	FILE *fp;
	//调用curl_easy_init()函数得到 easy interface型指针
	CURL *curl = curl_easy_init();
	if (curl)
	{
		fopen_s(&fp, strFile.c_str(), "wb");

		CURLcode res = curl_easy_setopt(curl, CURLOPT_URL, strUrl.c_str());
		if (res != CURLE_OK)
		{
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}

		res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
		if (res != CURLE_OK)
		{
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}

		res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
		if (res != CURLE_OK)
		{
			fclose(fp);
			curl_easy_cleanup(curl);
			return -1;
		}
		curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);		
		curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback);//设置进度回调函数
		curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
		//开始执行请求
		res = curl_easy_perform(curl);
		fclose(fp);
		/* Check for errors */
		if (res != CURLE_OK)
		{
			curl_easy_cleanup(curl);
			return -1;
		}
		curl_easy_cleanup(curl);//调用curl_easy_cleanup()释放内存
	}

	return 0;
}
//
void EasyCurl::set_progress_function(ProgressFunction func)
{
	m_updateProgress = func;
}
//
void EasyCurl::set_progress_callback(IProgressCallback *pCallback)
{ 
	m_pHttpCallback = pCallback; 
}
//
void EasyCurl::SetDebug(bool bDebug)
{
	m_bDebug = bDebug;
}

2013-10-10 10:45:05 iteye_8088 阅读数 1066
  • cURL实战教程

    由King老师精心打造cURL实战课程,由浅入深的讲解了cURL中常见的API,及cURL在实际开发中的应用,实现了模拟登陆、文件上传下载、多线程cURL等。通过cURL可以操作各种网络资源! 山哥出品,必属精品!

    16023 人正在学习 去看看 何山

HTTPPost发送JSON:

private static final String APPLICATION_JSON = "application/json";
    
    private static final String CONTENT_TYPE_TEXT_JSON = "text/json";

public static void httpPostWithJSON(String url, String json) throws Exception {
        // 将JSON进行UTF-8编码,以便传输中文
        String encoderJson = URLEncoder.encode(json, HTTP.UTF_8);
        
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);
        
        StringEntity se = new StringEntity(encoderJson);
        se.setContentType(CONTENT_TYPE_TEXT_JSON);
        se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON));
        httpPost.setEntity(se);
        httpClient.execute(httpPost);
    }


接收HTTPPost中的JSON:

public static String receivePost(HttpServletRequest request) throws IOException, UnsupportedEncodingException {
        
        // 读取请求内容
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while((line = br.readLine())!=null){
            sb.append(line);
        }


        // 将资料解码
        String reqBody = sb.toString();
        return URLDecoder.decode(reqBody, HTTP.UTF_8);
    }
2017-06-25 16:30:56 miner_k 阅读数 2295
  • cURL实战教程

    由King老师精心打造cURL实战课程,由浅入深的讲解了cURL中常见的API,及cURL在实际开发中的应用,实现了模拟登陆、文件上传下载、多线程cURL等。通过cURL可以操作各种网络资源! 山哥出品,必属精品!

    16023 人正在学习 去看看 何山

LAMP环境:Apache 2.4 + MySQL 5.7.17 + PHP 7.1.6

部署环境:

[root@miner_k ~]# cat /etc/redhat-release 
CentOS release 6.8 (Final)

涉及的常用网络知识点(浅显易懂):

静态网页

静态网站:客户端访问web服务器,服务器直接从后端的资源中直接查找资源,如果有,直接返回。

**静态网站**  
        是指全部由HTML(标准通用标记语言的子集)代码格式页面组成的网站,所有的内容包含在网页文件中。网页上也可以出现各种视觉动态效果,如GIF动画、FLASH动画、滚动字幕等,而网站主要是静态化的页面和代码组成,一般文件名均以htm、html、shtml等为后缀

动态网页

动态网站: 在服务端或者是在客户端执行一段脚本或者程序,这个程序根据不同的客户端、不同用户、不同主机、不同场景,执行结果也不同。动态网站是根据用户请求做出对应响应,针对不同用户请求返回的结果是不同的结果

    **动态网页**
        是基本的html语法规范与Java、VB、VC等高级程序设计语言、数据库编程等多种技术的融合,以期实现对网站内容和风格的高效、动态和交互式的管理。因此,从这个意义上来讲,凡是结合了HTML以外的高级程序设计语言和数据库技术进行的网页编程技术生成的网页都是动态网页

注意:网页上的各种动画、滚动字幕等视觉上的动态效果并不是动态网页,动态网页也可以是纯文字内容的,也可以是包含各种动画的内容,这些只是网页具体内容的表现形式,无论网页是否具有动态效果,只要是采用了动态网站技术生成的网页都可以称为动态网页

客户端动态:服务器上的程序下载到客户端本地,然后在客户端运行,并将结果显示出来

服务器端动态:客户端发送请求到服务器上,服务器通过运行程序(服务器脚本)将运行的结果转换为HTML文件返回给客户端。

常用的4种动态网页技术:

  1. PHP 即Hypertext Preprocessor(超文本预处理器)
  2. ASP 即Active Server Pages(活跃服务器页),它是微软开发的一种类似超文本标识语言(HTML)、脚本(Script)与CGI(公用网关接口)的结合体,它没有提供自己专门的编程语言,而是允许用户使用许多已有的脚本语言编写ASP的应用程序
  3. JSP 即Java Server Pages(爪哇服务器页面),它是由Sun Microsystem公司于1999年6月推出的新技术,是基于Java Servlet以及整个Java(爪哇)体系的Web开发技术
  4. CGI(Common Gateway Interface,公用网关接口)是较早用来建立动态网页的技术。当客户端向Web服务器上指定的CGI程序发出请求时,Web服务器会启动一个新的进程执行某些CGI程序,程序执行后将结果以网页的形式再发送回客户端

CGI(Common Gateway Interface,公用网关接口)

CGI是外部应用程序(CGI程序)与WEB服务器之间的接口标准,是在CGI程序和Web服务器之间传递信息的过程。

工作过程:


 1. 浏览器通过HTML表单或超链接请求指向一个CGI应用程序的URL。
 2. 服务器收发到请求
 3. 服务器执行指定CGI应用程序
 4. CGI应用程序执行所需要的操作,通常是基于浏览者输入的内容
 5. CGI应用程序把结果格式化为网络服务器和浏览器能够理解的文档(通常是HTML网页)
 6. 网络服务器把结果返回到浏览器中

举例(论坛发布)
先由用户在客户端输入一些信息,接着用户按一下“发布或提交”(到目前为止工作都在客户端),浏览器把这些信息传送到服务器的CGI目录下特定的CGI程序中,于是CGI程序在服务器上按照预定的方法进行处理。在本例中就是把用户提交的信息存入指定的文件中。然后CGI程序给客户端发送一个信息,表示请求的任务已经结束。此时用户在浏览器里将看到“留言结束”的字样。


Apache + php的连接模式:

    CGI:
        Apache的进程管理php的进程,当php进程获取数据之后,会将结果返给web服务器,Apache的进程将php的进程关闭.Apache进程决定php进程的生命周期。如果客户端有200给请求,需要开启400个进程,200是Apache进程和200个php进程。

    Module:
        Apache是支持DSO(dynamic shared object 动态共享对象)将php作为Apache的模块(php_mod),如果客户端有200个请求只需要有200进程即可完成处理。Apache的进程中有php的功能。

     FastCGI:
         Apache的web服务器和php服务器分开,当客户端发送请求时,需要到php的服务器获取数据。该php的服务器可以提供CGI的进程,不需要Apache的进程控制CGI程序进程的生命周期。php服务器自行管理php的进程。

Apache + php(Module)

  • 安装Apache和php
[root@miner_k ~]# yum -y install httpd
[root@miner_k ~]# yum install php php-mbstring
  • Apache中关于php的配置
安装的php的rpm包:
        php-mbstring  支持字节
        php-cli         php的通用组件
        php-common      php的命令行



[root@miner_k ~]# rpm -ql php
/etc/httpd/conf.d/php.conf             # Apache中php的配置文件
/usr/lib64/httpd/modules/libphp5.so    # Apache中php模块
/var/lib/php/session
/var/www/icons/php.gif

[root@miner_k ~]# vim /etc/httpd/conf.d/php.conf
<IfModule prefork.c>        #Apache使用prefork模式,需要加载php的libphp5模块
  LoadModule php5_module modules/libphp5.so
</IfModule>
<IfModule worker.c>         #Apache使用worker模式,需要加载libphp5-zts模块
  LoadModule php5_module modules/libphp5-zts.so
</IfModule>


AddHandler php5-script .php      #添加处理php5-script的处理器,如果是.php文件需要Apache的php5-script解释器处理。
AddType text/html .php          #识别的类型

DirectoryIndex index.php        #默认主页
  • 添加php的测试网页
[root@miner_k ~]# cat /var/www/html/index.php 
<?php
phpinfo();
?>
  • 重新启动Apache服务器
[root@miner_k ~]# service httpd restart

php 和数据库连接的模型:

PHP:脚本编程语言,php解释器

WebApp:面向对象的特性
    Zend:php语言的解释器
        第一段:词法分析、语法分析、编译为Opcode;
            opcode放置于内存中
        第二段:执行opcode;

PHP 缓存器:
    APC
    eAccelerator
    XCache

这里写图片描述

这里写图片描述

ODBC 开放数据库系统互联
DBMS 数据库管理系统(Database Management System)
RDBMS 关系数据库管理系统(Relational Database Management System)


使用rpm包LAMP的部署

LAMP的架构:
    单层结构(部署在一个服务器上)
    二层结构(部署在两个服务器上)
    三层结构(部署在三个服务器上)

安装Apache、MySQL、PHP

[root@miner_k ~]# yum -y install httpd
[root@miner_k ~]# yum -y install php php-mbstring php-mysql
[root@miner_k ~]# yum -y install mysql-server  mysql

启动Apache、MySQL

[root@miner_k ~]#  service httpd start
[root@miner_k ~]#  service mysqld start 

设置MySQL的密码

[root@miner_k ~]# mysql
mysql> SET PASSWORD FOR 'root'@'localhost'=PASSWORD('123');
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

设置PHP连接MySQL的测试网页

[root@miner_k ~]# cat /var/www/html/index.php 
<?php
  $conn=mysql_connect('localhost','root','123');
  if ($conn)
    echo "Success...";
  else
    echo "Failure...";
?>

在LAMP部署常见的部署环境:

LAMP:
    phpMyAdmin

论坛:
    discuz
    phpwind
    phpbb

CMS:
    drupal
    joomla

LAMP
    wordpress: 个人博客系统

使用源码包安装LAMP

源码包部署的参考链接:http://www.lamphowto.com/

LAMP代表的是Linux、Apache、MySQL、PHP。当然此处的P也可以表示Perl、Python,但是一般情况下是指PHP。

安装开发工具:

[root@miner_k ~]# yum -y groupinstall "Development tools"
[root@miner_k ~]# yum -y install expat-devel

查找LAMP相关的rpm包

[root@miner_k ~]# rpm -qa | grep -i httpd
[root@miner_k ~]# rpm -qa | grep -i apahce
[root@miner_k ~]# rpm -qa | grep -i mysql
[root@miner_k ~]# rpm -qa | grep -i php

使用命令清除相关的安装包:

[root@miner_k ~]# rpm -e filename
[root@miner_k ~]# yum -y remove filename

Apache的安装

下载资源:

Apache的官网链接:http://httpd.apache.org/docs/2.4/install.html

apr可以看做事Apache的虚拟机,类似于java的JVM。便于环境的移植。

[root@miner_k ~]# wget http://mirror.bit.edu.cn/apache//httpd/httpd-2.4.26.tar.gz
[root@miner_k ~]# wget http://mirror.bit.edu.cn/apache//apr/apr-1.6.2.tar.gz
[root@miner_k ~]# wget http://mirror.bit.edu.cn/apache//apr/apr-util-1.6.0.tar.gz

做MD5校验:

[root@miner_k ~]# md5sum httpd-2.4.26.tar.gz 
492aeb0f752baf7e895fea6334dfe202  httpd-2.4.26.tar.gz
[root@miner_k ~]# curl https://www.apache.org/dist/httpd/httpd-2.4.26.tar.gz.md5
492aeb0f752baf7e895fea6334dfe202 *httpd-2.4.26.tar.gz
解压安装:
[root@miner_k ~]# tar -xf apr-1.6.2.tar.gz
[root@miner_k ~]#cd apr-1.6.2
[root@miner_k apr-1.6.2]# ./configure --prefix=/usr/local/apr
[root@miner_k apr-1.6.2]# make && make install

[root@miner_k apr-1.6.2]# tar -xvf apr-util-1.6.0.tar.gz
[root@miner_k ~]# cd apr-util-1.6.0
[root@miner_k apr-util-1.6.0]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr/
[root@miner_k apr-1.6.2]# make && make install


[root@miner_k ~]# tar -xf httpd-2.4.26.tar.gz 
[root@miner_k ~]# cd httpd-2.4.26
[root@miner_k httpd-2.4.26]# ./configure --prefix=/usr/local/apache --sysconfdir=/etc/httpd  --enable-so --enable-rewrite --enable-cgid --enable-cgi --enable-ssl --enable-modules=most --enable-mods-shared=most --enable-mpms-shared=all --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util
各参数的意义:

        --prefix=PREFIX   指定安装位置
        --sysconfdir=DIR   配置文件目录

        --enable-modules=MODULE-LIST                      Space-separated list of modules to enable | "all" |                         "most" | "few" | "none" | "reallyall"

        --enable-mods-shared=MODULE-LIST      开启共享模块Space-separated list of shared modules to enable |                                     "all" | "most" | "few" | "reallyall"

        --enable-proxy-fcgi    开启FastCGI module
        --enable-ssl        SSL/TLS support (mod_ssl)
        --enable-cgi        CGI scripts,非线程模式
        --enable-cgid        CGI scripts,线程模式
        --with-included-apr
        --with-apr=PATH                 指定apr模块
        --with-apr-util=PATH            指定apr-util的路径
        --with-ssl=PATH 

        --enable-rewrite    支持URL重写
        --enable-so            Dynamic SharedObjects(动态共享目标) DSO capability. This module will be automatically enabled unless you build all modules statically            

        -enable-mpms-shared=MPM-LIST    Space-separated list of MPM modules to enable for
                                                               dynamic loading. MPM-LIST=list | "all"            
        --with-mpm=MPM      设置MPM的默认模式

[root@miner_k httpd-2.4.26]# make && make install

修改配置文件(将pid文件存放到指定的位置)
[root@miner_k apache]# vim /etc/httpd/httpd.conf
PidFile "/var/run/httpd.pid"
设置httpd的启动脚本
[root@miner_k ~]# vim httpd
#!/bin/bash
. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/httpd ]; then
        . /etc/sysconfig/httpd
fi

HTTPD_LANG=${HTTPD_LANG-"C"}

INITLOG_ARGS=""

#修改为源码包安装Apache的apachectl的存放位置
apachectl=/usr/local/apache/bin/apachectl

#httpd命令的存放位置
httpd=${HTTPD-/usr/local/apache/bin/httpd}
prog=httpd

#httpd的pid文件的存放位置
pidfile=${PIDFILE-/var/run/httpd.pid}
lockfile=${LOCKFILE-/var/lock/subsys/httpd}
RETVAL=0
STOP_TIMEOUT=${STOP_TIMEOUT-10}

start() {
        echo -n $"Starting $prog: "
        LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch ${lockfile}
        return $RETVAL
}

stop() {
    status -p ${pidfile} $httpd > /dev/null
    if [[ $? = 0 ]]; then
        echo -n $"Stopping $prog: "
        killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
    else
        echo -n $"Stopping $prog: "
        success
    fi
    RETVAL=$?
    echo
    [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

reload() {
    echo -n $"Reloading $prog: "
    if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then
        RETVAL=6
        echo $"not reloading due to configuration syntax error"
        failure $"not reloading $httpd due to configuration syntax error"
    else
        # Force LSB behaviour from killproc
        LSB=1 killproc -p ${pidfile} $httpd -HUP
        RETVAL=$?
        if [ $RETVAL -eq 7 ]; then
            failure $"httpd shutdown"
        fi
    fi
    echo
}

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  status)
        status -p ${pidfile} $httpd
    RETVAL=$?
    ;;
  restart)
    stop
    start
    ;;
  condrestart|try-restart)
    if status -p ${pidfile} $httpd >&/dev/null; then
        stop
        start
    fi
    ;;
  force-reload|reload)
        reload
    ;;
  graceful|help|configtest|fullstatus)
    $apachectl $@
    RETVAL=$?
    ;;
  *)
    echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"
    RETVAL=2
esac

exit $RETVAL


[root@miner_k ~]# chmod +x httpd
[root@miner_k ~]# cp httpd /etc/init.d/
启动Apache服务:
如果没有设置启动脚本:
[root@miner_k apache]# pwd
/usr/local/apache
[root@miner_k apache]# bin/apachectl start

设置了启动脚本
[root@miner_k ~]# service  httpd restart

开机自启动
[root@miner_k ~]# chkconfig --add httpd
[root@miner_k ~]# chkconfig httpd on
让Apache使用prefork模式启动
[root@miner_k apache]# vim /etc/httpd/httpd.conf 
.....
#LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
......

[root@miner_k ~]# service  httpd restart

mysql的部署和安装(通用二进制)

[root@miner_k ~]# wget https://downloads.mysql.com/archives/get/file/mysql-5.7.17-linux-glibc2.5-x86_64.tar.gz

shell> groupadd mysql
shell> useradd -r -g mysql -s /bin/false mysql
shell> cd /usr/local
shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz
shell> ln -s full-path-to-mysql-VERSION-OS mysql

#切换到数据库的basedir目录下
[root@miner_k mysql]# cd mysql   

# 用来存放系统变量secure_file_priv的值,限制导入和导出的
[root@miner_k mysql]# mkdir mysql-files 
[root@miner_k mysql]# chmod 750 mysql-files

#确保mysql用户有权限
[root@miner_k mysql]# chown -R mysql .
[root@miner_k mysql]# chgrp -R mysql .

# MySQL 5.7.6之前使用的初始化命令
[root@miner_k mysql]# bin/mysql_install_db --user=mysql    

# MySQL 5.7.6开始使用的初始化命令
[root@miner_k mysql]# bin/mysqld --initialize --user=mysql
2017-07-03T05:47:41.665070Z 1 [Note] A temporary password is generated for root@localhost: Ow(0SW.ky.NN 

#创建SSL 和 RSA,自动设置安全连接MySQL 5.7.6已上
[root@miner_k mysql]# bin/mysql_ssl_rsa_setup     

#设置文件的所有权       
[root@miner_k mysql]# chown -R root .
[root@miner_k mysql]# chown -R mysql data mysql-files
#注:如果mysql服务创建一些文件,例如SELECT ... INTO DUMPFILE.创建的目录,要保证改目录或者是文件能被mysql服务读取。权限设置和mysql-files类似。
数据库初始化:

数据库的初始化主要是生成’root’@’localhost’账户的随机密码

shell> bin/mysqld --initialize --user=mysql
shell> bin/mysqld --initialize-insecure --user=mysql
参数:

    --initialize   为mysql的root用户生成随机密码
    --initialize-insecure  不生成密码。如果已经提前设置好了密码。
    --user=mysql   如果是使用mysql登录,可以忽略
    --basedir=/opt/mysql/mysql    安装目录
    --datadir=/opt/mysql/mysql/data    数据目录
    --defaults-file=/opt/mysql/mysql/etc/my.cnf    调用配置文件

将datadir设置为其他位置:

#创建数据库的数据存放位置并设置权限
[root@miner_k mysql]# mkdir /var/lib/mysql
[root@miner_k mysql]# chown -R mysql:mysql /var/lib/mysql

#切换到安装路径
[root@miner_k mysql]# cd /usr/local/mysql

#初始化数据库(空密码)
[root@miner_k mysql]# bin/mysqld --initialize-insecure --user=mysql --datadir=/var/lib/mysql/

#修改配置文件,方便mysql服务加载到对应的文件
[root@miner_k local]# cat /etc/my.cnf
[mysqld]
datadir=/var/lib/mysql/
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
[client] 
port=3306 
socket=/var/lib/mysql/mysql.sock 
default-character-set=utf8

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
加载的配置文件:

mysql的配置文件:

/etc/my.cnf  ---> /etc/mysql/my.cnf  ---> $BASEDIR/my.cnf  ---> $DATADIR/my.cnf ---> ~/.my.cnf

配置文件的后一个会覆盖前一个。

启动mysqld
[root@miner_k mysql]# service mysqld start



#mysql启动的两种方式:
shell> bin/mysqld_safe --user=mysql &
# Next command is optional
shell> cp support-files/mysql.server /etc/init.d/mysql.server


[root@miner_k mysql]# cp support-files/mysql.server /etc/init.d/mysqld
[root@miner_k mysql]# chkconfig --add mysqld
配置环境变量
[root@miner_k ~]# vim /etc/profile.d/mysqld.sh
export PATH=$PATH:/usr/local/mysql/bin
[root@miner_k ~]# source /etc/profile.d/mysqld.sh
客户端连接mysql
#如果初始化的时候没有设置密码,密码为空,如果初始化有随机密码需要输入尝试的随机密码。

shell> mysql -u root -p
Enter password: (enter the random root password here)

mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';

php的部署和安装(module方式连接Apache,mysqli连接MySQL)

[root@miner_k LAMP]# yum -y install libxml2 libxml2-devel
[root@miner_k LAMP]# yum install openssl openssl-devel
[root@miner_k LAMP]# yum -y install bzip2-devel
[root@miner_k LAMP]# tar -xvf php-7.1.6.tar.gz -C /usr/local/
[root@miner_k LAMP]# cd /usr/local/php-7.1.6/

[root@miner_k php-7.1.6]# ./configure --prefix=/usr/local/php --with-pdo-mysql=/usr/local/mysql --with-openssl --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml  --enable-sockets --with-apxs2=/usr/local/apache/bin/apxs   --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-bz2

[root@miner_k php-7.1.6]# make
[root@miner_k php-7.1.6]# make install

     参数:
        --prefix=/usr/local/php            #安装路径
        --with-mysql=/usr/local/mysql      #mysql的安装路径
        --with-openssl                     #支持openssl功能
        --with-mysqli=/usr/local/mysql/bin/mysql_config   #mysql的另一种接口
        --enable-mbstring                  #多字节的字符
        --with-freetype-dir                #字体库,可以引用特定字体
        --with-jpeg-dir                    #jpeg图片
        --with-png-dir 
        --with-zlib                        # 通用压缩库
        --with-libxml-dir=/usr             #xml的库文件
        --enable-xml  
        --enable-sockets                   #基于套接字通信
        --with-apxs2=/usr/local/apache/bin/apxs   #让php编译成Apache的模块
        --with-mcrypt                      #支持加密  
        --with-config-file-path=/etc    #php的配置文件存放路径
        --with-config-file-scan-dir=/etc/php.d   #配置文件包含/etc/php.d/*.ini
        --with-bz2                          #bz2压缩
        --enable-maintainer-zts             #Apache如果是线程方式(event、worker)工作就使用这种方式,如果是prefork模式不需要。
        --enable-fpm               #使用FastCGI模式

修改Apache的配置文件

[root@miner_k php]# vim /etc/httpd/httpd.conf

#增加默认网页为index.php
<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>

#增加php的解释器
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps

检查Apache配置文件的语法

[root@miner_k php]# httpd -t
Syntax OK

重新启动Apache

[root@miner_k php]# service httpd restart
Stopping httpd:                                [  OK  ]
Starting httpd:                                [  OK  ]

修改Apache的默认主页

[root@miner_k php]# cd /usr/local/apache/htdocs/
[root@miner_k htdocs]# mv index.html{,.bak} 

#测试Apache中php模块的加载情况
[root@miner_k htdocs]# vim index.php
<?php
phpinfo();
?>
#连接mysql的测试:
#php7中不能使用mysql_connet()函数,只能使用mysqli()函数。
<?php
$mysqli = new mysqli("localhost", "root", "123", "student");
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
echo $mysqli->host_info . "\n";

$mysqli = new mysqli("127.0.0.1", "root", "123", "student", 3306);
if ($mysqli->connect_errno) {
    echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}

echo $mysqli->host_info . "\n";

//#获取student库中的st1表中的内容
$sql = "select * from st1";
//执行sql语句,完全面向对象的
$result = $mysqli->query($sql);
while($row = $result->fetch_array()){
echo $row[0]
?>

输出结果:
Localhost via UNIX socket
127.0.0.1 via TCP/IP

注:在使用该方式连接mysql时,需要修改php.ini中的mysqli.default_socket变量,设置为mysql的socket文件。


PHP的部署和安装(FastCGI连接Apache)

在PHP服务器上的配置
下载PHP的源码包并解压
[root@miner_k ~]# yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2-devel
[root@miner_k ~]# yum -y groupinstall "Development Tools"

[root@miner_k ~]# tar -xvf php-7.1.6.tar.gz
[root@miner_k ~]# cd php-7.1.6
[root@miner_k php-7.1.6]# ./configure --prefix=/usr/local/php --with-openssl --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-mbstring --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml  --enable-sockets  --with-config-file-path=/etc --with-config-file-scan-dir=/etc/php.d --with-bz2 --enable-fpm
参数:

编译 PHP 时需要 --enable-fpm 配置选项来激活 FPM 支持。

以下为 FPM 编译的具体配置参数(全部为可选参数):

    --with-fpm-user - 设置 FPM 运行的用户身份(默认 - nobody)
    --with-fpm-group - 设置 FPM 运行时的用户组(默认 - nobody)
    --with-fpm-systemd - 启用 systemd 集成 (默认 - no)
    --with-fpm-acl - 使用POSIX 访问控制列表 (默认 - no) 5.6.5版本起有效
编译、安装
[root@miner_k php-7.1.6]# make
[root@miner_k php-7.1.6]# make install
复制配置文件
[root@miner_k php-7.1.6]# cp php.ini-production /etc/php.ini
设置启动脚本
[root@miner_k php-7.1.6]# cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
[root@miner_k php-7.1.6]# chmod +x /etc/init.d/php-fpm 
[root@miner_k php-7.1.6]# chkconfig --add php-fpm
设置php-fpm的配置文件
[root@miner_k php-7.1.6]# cd /usr/local/php/
[root@miner_k php]# cp etc/php-fpm.conf{.default,}
[root@miner_k etc]# cp php-fpm.d/www.conf{.default,}
[root@miner_k php]# egrep -v "^$|;" /usr/local/php/etc/php-fpm.d/www.conf

[www]
user = nobody
group = nobody
listen = 0.0.0.0:9000              #监听所有的IPV4,如果是本机可以设置127.0.0.1
pm = dynamic
pm.max_children = 5             #最大进程数
pm.start_servers = 2                #开启时的进程数
pm.min_spare_servers = 1        #最小空闲进程
pm.max_spare_servers = 3        #最大空闲进程
access.log = log/$pool.access.log  # 开启访问日志

参数配置参考:http://php.net/manual/zh/install.fpm.configuration.php

设置php脚本
[root@miner_k php]# cat /var/www/index.php 
<?php
phpinfo();
?>
启动php-fpm
[root@miner_k etc]# service php-fpm start
Starting php-fpm  done
[root@miner_k etc]# netstat -anlp | grep :9000
tcp        0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN      86182/php-fpm 
Apache服务器上的配置:

[root@miner_k ~]# vim /etc/httpd/httpd.conf


#需要加载的模块
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

#下面两行和servername是同一级别的
ProxyRequests Off
ProxyPassMatch ^/(.*\.php)$ fcgi://$IP:9000/var/www/$1 #"$1" 代表的上"(" ")" 中的php网页  
#$IP 要设置php-fpm的服务器的IP地址

<IfModule dir_module>
    DirectoryIndex index.php index.html
</IfModule>

#以下这两行可省略
#AddType application/x-httpd-php .php
#AddType application/x-httpd-php-source .phps

重新启动Apache的服务

[root@miner_k ~]# service httpd restart
Stopping httpd:                                 [  OK  ]
Starting httpd:                                 [  OK  ]    

常见错误

在定制apr时报错:rm: cannot remove `libtoolT’: No such file or directory

检查libtool-2.2.6-15.5.el6.x86_64 包我是安装了的

[root@lsw-centos65 ~]# rpm -qa | grep libtool
libtool-2.2.6-15.5.el6.x86_64

修改配置文件中的内容:

修改前:
[root@lsw-centos65 apr-1.6.2]# grep -n "RM='\$RM" configure
30350:    RM='$RM'

修改之后:
[root@lsw-centos65 apr-1.6.2]# grep -n "RM='\$RM" configure
30350:    RM='$RM -f'

1.在编译apr-util是报错
[root@miner_k apr-util-1.6.0]#make
xml/apr_xml.c:35:19: error: expat.h: No such file or directory
xml/apr_xml.c:66: error: expected specifier-qualifier-list before ‘XML_Parser’
xml/apr_xml.c: In function ‘cleanup_parser’:
xml/apr_xml.c:364: error: ‘apr_xml_parser’ has no member named ‘xp’
xml/apr_xml.c: At top level:
xml/apr_xml.c:384: error: expected ‘;’, ‘,’ or ‘)’ before ‘*’ token
xml/apr_xml.c: In function ‘apr_xml_parser_create’:
xml/apr_xml.c:401: error: ‘apr_xml_parser’ has no member named ‘xp’
xml/apr_xml.c:424: error: ‘default_handler’ undeclared (first use in this function)
xml/apr_xml.c:424: error: (Each undeclared identifier is reported only once
xml/apr_xml.c:424: error: for each function it appears in.)
xml/apr_xml.c: In function ‘do_parse’:
xml/apr_xml.c:434: error: ‘apr_xml_parser’ has no member named ‘xp’
xml/apr_xml.c: In function ‘apr_xml_parser_geterror’:
xml/apr_xml.c:500: error: ‘apr_xml_parser’ has no member named ‘xp_err’
make[1]: *** [xml/apr_xml.lo] Error 1
make[1]: Leaving directory `/root/apr-util-1.6.0'
make: *** [all-recursive] Error 1


解决方法:

[root@miner_k apr-util-1.6.0]# yum -y install expat-devel
2.定制httpd时报错
[root@miner_k httpd-2.4.26]# ./configure --prefix=/usr/local/apache
......
checking for pcre-config... false
configure: error: pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/

解决方法:

[root@miner_k httpd-2.4.26]# yum -y install pcre-devel
3.启动httpd是报错
[root@miner_k ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: AH00557: httpd: apr_sockaddr_info_get() failed for miner_k.example.com
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs
                                                           [FAILED]

1.报错提示:AH00557: httpd: apr_sockaddr_info_get() failed for miner_k.example.com

解决方法:

[root@miner_k ~]# cat /etc/hosts
    127.0.0.1 miner_k.example.com
2.**报错提示:**AH00558: httpd: Could not reliably determine the server’s fully qualified domain name, using 127.0.0.1. Set the ‘ServerName’ directive globally to suppress this message

解决方法(修改配置文件):

ServerName miner_k.example.com:80
3.报错提示:(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80no listening sockets available, shutting down AH00015: Unable to open logs

解决方法:
报错提示显示80端口以及被占用。
查找80端口的程序,然后关闭程序。


安装php报错

查看链接:http://www.poluoluo.com/jzxy/201505/364819.html

运行./configure报错
## 错误提示:“xml2-config not found”
checking libxml2 install dir... no
checking for xml2-config path... 
configure: error: xml2-config not found. Please check your libxml2 installation
解决方法:

```
# yum -y install libxml2 libxml2-devel
```
错误提示:configure: error: Cannot find OpenSSL’s
解决方法:

```
#   yum install openssl openssl-devel
#   ln -s /usr/lib64/libssl.so /usr/lib/
```
错误提示: Please reinstall the BZip2 distribution
checking for BZip2 in default path... not found
configure: error: Please reinstall the BZip2 distribution
解决方法:

```
yum -y install bzip2-devel
```
使用php连接mysql时,提示:Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’

报错:Failed to connect to MySQL: (2002) Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’

分析:此处提示的使用localhost连接时,使用的socket文件和设置的mysql的socket文件不一致。故需要修改socket文件的位置。如果使用socket的文件和自己设置的一样需要修改mysql的root@localhost的用户的密码。

解决方法(设置mysql的socket文件):

[root@miner_k php-7.1.6]# vim /etc/php.ini
mysqli.default_socket =/var/lib/mysql/mysql.sock
2018-01-03 17:44:00 weixin_33949359 阅读数 6
  • cURL实战教程

    由King老师精心打造cURL实战课程,由浅入深的讲解了cURL中常见的API,及cURL在实际开发中的应用,实现了模拟登陆、文件上传下载、多线程cURL等。通过cURL可以操作各种网络资源! 山哥出品,必属精品!

    16023 人正在学习 去看看 何山
手游Unity:
C#、AI、Editor、Shader、内存优化、网络热更新、FSM有限状态机、UI框架、战斗系统、游戏客户端架构、3D数学、游戏引擎(鬼火、ORGE等)。
 
后台:
C++、LUA、网络模式(reactor、proactor等)、不同平台下的阻塞或非阻塞模式(Windows/IOCP/Select,Linux/Epoll)、开源网络库(CURL、LIBEVENT、ACE、NGINX、MUDUO、AISO)、
数据库(MYSQL、REDIS、LEVELDB、MOGODB)、开源游戏服务器框架、新兴语言以及其开源框架架构(NODE.JS、GO等)、云服务,微服务。
 
端游:
Win32基础、WTL、ATL、MFC、COM、DirectX、OpenGL
 
其他:
数据结构与算法、设计模式,操作系统
 
根据某个知识点进行更新。
 

转载于:https://www.cnblogs.com/xiuxiu55/p/8184925.html

没有更多推荐了,返回首页