有位朋友让我给他新开的网站帮忙做几个小功能,如下:

  1. 输入快递公司、快递单号,查询出这个快件的所有动态(从哪里出发,到了哪里)
  2. 在注册、登录等场景下的手机验证码(要求有一定的防刷策略)
  3. 通过输入公司名的关键词,查看这个公司是否已经注册、法人信息、有类似名称的公司等等

并且可以用的接口、文档都提供给我了。
其中需求 1、2,都通过 聚合数据 这家网站提供的接口实现;需求 3 通过 云聚数据 来实现。

本项目的文件

因为朋友的网站是用 ThinkPHP 写的,为了保持将来代码的兼容,这三个功能也用 ThinkPHP 写成。

项目的所有文件都放在了 GitHub 上,部分敏感数据已经隐藏,你需要自行替换,地址如下:

GitHub 地址:使用聚合数据API查询快递数据-短信验证码-企业核名

因为这三个功能并不是正式产品,将来会需要嵌入到网站的各个功能模块中去,所以为了查看起来方便,三个功能的代码都写在一个文件里,你只要重点关注以下几个文件就好:

  • /Home/Conf/config.php 参数配置文件
  • /Home/Controller/IndexController.class.php 后端代码、API的请求与处理
  • /Home/View/Index_index.html 前端 html

申请 KEY 和阅读开发文档

分别到上面两家网站上找到“快递”、“短信”、“核名”的文档地址,根据里面的说明,把 KEY、URL 等信息放入配置文件Home/Conf/config.php,方便后面重复使用。

常用快递API文档

短信API文档

核名-文档

注意 短信的 API 服务,要先到网站的后台添加“短信模板”,让管理员审核后才可以正常调用

最后,Home/Conf/config.php 配置文件里的内容如下

return array(
// 快递查询
'EXPRESS_APP_KEY' => '你的快递 APPKEY',
'EXPRESS_QUERY_URL' => 'http://v.juhe.cn/exp/index', //快递单号查询
'EXPRESS_COM_URL' => 'http://v.juhe.cn/exp/com', //快递公司查询
// 发短信
'SEND_SMS_KEY' => '你的短信接口 APPKEY',
'SEND_SMS_URL' => 'http://v.juhe.cn/sms/send',
// 核名
'COMPANY_KEY' => '核名 APPKEY',
'COMPANY_URL' => 'http://eci.yjapi.com/ECIFast/Search',
//数据库配置信息
'DB_TYPE' => 'mysql', // 数据库类型
'DB_HOST' => 'localhost', // 服务器地址
'DB_NAME' => '你的数据库名', // 数据库名
'DB_USER' => '你的数据库用户名', // 用户名
'DB_PWD' => '密码', // 密码
'DB_PORT' => 3306, // 端口
'DB_PREFIX' => 'pre_', // 数据库表前缀
'DB_CHARSET'=> 'utf8', // 字符集
);

设置数据库

为了防止恶意用户利用暴露在外的短信接口捣乱,需要对每个手机号码的行为进行记录。例如:

  • 向某个手机号码发送短信验证码后, 60 秒内不能再次发送
  • 必须在 1 小时内填写短信验证码,否则会过期
  • 避免 ajax 请求地址被机器人程序利用,在表单里要使用图片验证码才能提交数据

关于“表单验证码”我们后面代码会说明,这里先创建表结构如下,用于记录短信发送记录:

CREATE TABLE `pre_smsrecord` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`mobile` varchar(11) NOT NULL DEFAULT '',
`tpl_id` int(11) NOT NULL,
`code` int(6) NOT NULL,
`time` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=M
  • mobile 是手机号码
  • tpl_id是在网站后台添加并通过审核的短信模板
  • code是发送的验证码(一般是4位或6位)
  • time是发送时间戳

直接下载sql进行还原:在本项目的 GitHub 地址上也可以直接从 /Pubic 目录找到 sql 文件,你可以直接把它还原你的 MySQL 上。

表单验证码的实现

最终效果如下:

因为三个功能都需要表单验证码,所以首先实现它。

打开 /Home/View/Index_index.html,注意里面图片验证码 img 标签,以及对应的 javascript

<p>
(通用)输入验证码 <input type="text" name="verify" id="verify">
<img id="verify-img" src="/?m=Home&c=Index&a=verify" alt="">
<a id="btn-refresh-verify" href="javascript:;" title="">刷新</a>
</p>
<script type="text/javascript" charset="utf-8">
jQuery(document).ready(function($) {
// 刷新验证码按钮
$("#btn-refresh-verify").click(function(event) { $("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime());
});
});
</script>

对应的后端代码在 /Home/Controller/IndexController.class.php 中

/**
* +--------------------------------------------------------------------------
* 生成验证码
*
* +--------------------------------------------------------------------------
*/
public function verify(){
$Verify = new \Think\Verify();
$Verify->entry();
}
/**
* +--------------------------------------------------------------------------
* 检查验证码
*
* @param string $code 输入的验证码
* @return boolean
* +--------------------------------------------------------------------------
*/
protected function check_verify($code){
$verify = new \Think\Verify();
return $verify->check($code);
}

通用的 Curl 方法,用来向第三方网站的 API 发起请求并获取返回值

因为 3 个功能实际上都是通过网络来请求一个第三方网站的 API 接口地址,因此可以统一成一个通用的方法。代码如下,可以传入三个变量,分别为 :url、参数数组、请求方式(是否是post,默认为0),返回一个 json 格式的数据。

/**
* +--------------------------------------------------------------------------
* 通用的“聚合数据”请求接口,返回JSON数据
*
* @param string $url 接口地址
* @param array $params 传递的参数
* @param int $ispost 是否以POST提交,默认GET
* @return json
* +--------------------------------------------------------------------------
*/
public function juhecurl($url,$params=false,$ispost=0){
$httpInfo = array();
$ch = curl_init();
curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 );
curl_setopt( $ch, CURLOPT_TIMEOUT , 30);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true );
if( $ispost )
{
curl_setopt( $ch , CURLOPT_POST , true );
curl_setopt( $ch , CURLOPT_POSTFIELDS , $params );
curl_setopt( $ch , CURLOPT_URL , $url );
}
else
{
if($params){
curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params );
}else{
curl_setopt( $ch , CURLOPT_URL , $url);
}
}
$response = curl_exec( $ch );
if ($response === FALSE) {
//echo "cURL Error: " . curl_error($ch);
return false;
}
$httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE );
$httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) );
curl_close( $ch );
return $response;
}

后面我们获取快递数据、发送短信、查询企业名称,都可以调用这个通用的方法。

获取快递数据列表的实现

最终效果如下:

打开 /Home/View/Index_index.html

<h1>获取快递数据</h1>
<div id="express-module">
<p>
选择公司
<select name="express-company" id="express-company">
<option value="sf">顺丰</option>
<option value="sto">申通</option>
<option value="yt">圆通</option>
<option value="yd">韵达</option>
<option value="tt">天天</option>
<option value="ems">EMS</option>
<option value="zto">中通</option>
<option value="ht">汇通</option>
</select>
</p>
<p>
输入单号 <input type="text" name="express-number" id="express-number">
</p>
<p>
<button id="btn-query-express" type="button" class="btn btn-default">查询快递</button>
</p> <p>返回结果:</p>
<p id="reason" style="color:#FF0000"></p> <p>快件动态:</p>
<ul id="express-result"> </ul>
</div>
<!-- 引入jquery库 -->
<script src="__PUBLIC__/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" charset="utf-8">
jQuery(document).ready(function($) {
//点击快递查询按钮
$("#btn-query-express").click(function(event) {
$("#reason").html("");
// 更新验证码
$("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime());
$.getJSON(
'/?m=Home&c=Index&a=getExpressData',
{
company: $("#express-company").val(),
number: $("#express-number").val(),
verify: $("#verify").val(),
},
function(json, textStatus) {
if(json['resultcode'] == 200){
var result_list = json['result']['list'];
$("#express-result").html("");
for(var i = 0, l = result_list.length; i < l; i++) {
$("#express-result").append("<li>" + result_list[i]['datetime'] + "," + result_list[i]['remark'] + "," +result_list[i]['zone'] + "</li>");
}
}
$("#reason").html(json['reason']);
});
});
});
</script>

对应的后端代码为如下,特别注意,你要把 $content = $this->juhecurl(C("EXPRESS_QUERY_URL"), $params, 1); 这段的注释去掉(因为我开发的时候查询余额不足,所以使用了一个写死的数组来让程序能正常运行)

/**
* +--------------------------------------------------------------------------
* 获取快递数据
*
* @param string $get.company 快递公司代码
* @param string $get.number 快递单号
* @return json
* +--------------------------------------------------------------------------
*/
public function getExpressData(){
// 传入 get 参数,包括公司代号、快递单号、验证码
$com = I("get.company");
$no = I("get.number");
$verify = I("get.verify");
// 处理验证码
if ( !$this->check_verify($verify) ) {
$content = array('resultcode'=>1000, 'reason'=>'验证码填写错误');
echo json_encode($content);
exit();
}
// 处理机器人程序刷接口(目前通过IP判断)
$ip = get_client_ip(0, true);
$Record = M("expressrecord");
$express_record = $Record->where("ip='" . $ip . "'")->find();
if( $express_record && ( (time() - $express_record['time']) < 60 ) ){
echo json_encode(array('reason'=>'60秒内只能查询一次'));
exit();
}
if ( $com && $no ) {
$params = array(
'key' => C("EXPRESS_APP_KEY"),
'com' => $com,
'no' => $no
);
// 开发测试阶段直接返回值,不请求 API
// $content = $this->juhecurl(C("EXPRESS_QUERY_URL"), $params, 1);
$content = array('resultcode'=>200, 'reason'=>'查询成功', 'result'=>array('list'=>array()));
// 删除旧记录(如果有),然后添加新的记录
$Record->where("ip='" . $ip . "'")->delete();
$data = array(
'ip' => $ip,
'time'=>time()
);
$Record->add($data);
//$returnArray = json_decode($content,true);
echo json_encode($content, true);
}
}

短信验证码的发送和检验

废话不多说,前端html直接上代码。这里实际上有两个动作,一个是“给我手机号码 xxxxx 发个验证码”,另一个是“我已经收到了,并填写了,请看我填写的验证码对不对”。

<h1>发送短信验证码与检查</h1>
<div id="sms-module">
<p>
短信模板:
<select name="send-sms-tplid" id="send-sms-tplid">
<option value="5596">申请注册</option>
<option value="5602">申请找回密码</option>
<option value="5603">在线核名</option>
</select>
</p> <p>
手机号码:<input type="text" name="send-sms-mobile" id="send-sms-mobile">
</p> <p>
输入手机验证码:<input type="text" name="send-sms-code" id="send-sms-code">
<span id="sms-count-down"></span>
<button id="btn-send-sms" type="button" class="btn btn-default">发送验证码</button>
</p> <p>
<button id="btn-check-sms" type="button" class="btn btn-default">提交手机验证码</button>
</p>
</div>
<script type="text/javascript" charset="utf-8">
/**
* 发送短信验证码后,60秒倒计时
*/
var seconds_left = 60;
function sms_count_down(){
if(seconds_left > 0){
seconds_left = seconds_left-1;
//var b=new Date(); document.getElementById("sms-count-down").innerHTML = seconds_left + "秒";
setTimeout("sms_count_down()",1000);
} else {
//根据 http://stackoverflow.com/questions/7526601/setattributedisabled-false-changes-editable-attribute-to-false
// 不能为 setAttribute 设置任何值,都会变成 ”disabled“,要使用 removeAttribute
document.getElementById("btn-send-sms").removeAttribute("disabled");
document.getElementById("btn-send-sms").innerHTML = "重新发送";
document.getElementById("sms-count-down").innerHTML = "";
}
}
jQuery(document).ready(function($) {
//发送短信
$("#btn-send-sms").click(function(event) {
$("#reason").html("");
$.getJSON(
'/?m=Home&c=Index&a=sendSMS',
{
tplid: $("#send-sms-tplid").val(),
mobile: $("#send-sms-mobile").val(),
},
function(json, textStatus) {
$("#reason").html(json['reason']);
var error_code = json['error_code'];
if(error_code == 0){
// 测试阶段,不禁用,可检查 60 秒重复发送
//$("#btn-send-sms").attr("disabled", true);
//开始倒计时
sms_count_down();
}else{
$("#btn-send-sms").html("重新发送");
} });
});
//检查短信验证码
$("#btn-check-sms").click(function(event) {
$("#reason").html("");
// 更新验证码
$("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime());
$.getJSON(
'/?m=Home&c=Index&a=checkSmsCode',
{
tplid: $("#send-sms-tplid").val(),
mobile: $("#send-sms-mobile").val(),
code: $("#send-sms-code").val(),
verify: $("#verify").val(),
},
function(json, textStatus) {
$("#reason").html(json['reason']); });
}); });

同样因为有两个动作,后端会稍微复杂一点点

/**
* +--------------------------------------------------------------------------
* 请求发送短信接口,60秒后才能重新发送
*
* @param int $get.tplid 短信模板id
* @param string $get.mobile 手机号码
* @return json
* +--------------------------------------------------------------------------
*/
public function sendSMS(){
$tpl_id = I("get.tplid"); // 短信模板id:注册 5596 找回密码 5602 在线核名 5603
$mobile = I("get.mobile"); // 手机号码
// 检查数据库记录 ,是否在 60 秒内已经发送过一次
$Record = M("smsrecord");
$where = array(
'mobile' => $mobile,
'tpl_id' => $tpl_id,
);
$sms_record = $Record->where($where)->find();
if( $sms_record && ( (time() - $sms_record['time']) < 60 ) ){
echo json_encode(array('reason'=>'60秒内不能多次发送'));
exit();
}
// 如果60秒内没有发过,则发送验证码短信(6位随机数字)
$code = mt_rand(100000, 999999);
$smsConf = array(
'key' => C("SEND_SMS_KEY"), //您申请的APPKEY
'mobile' => $mobile, //接受短信的用户手机号码
'tpl_id' => $tpl_id, //您申请的短信模板ID,根据实际情况修改
'tpl_value' =>'#code#=' . $code //您设置的模板变量,根据实际情况修改 '#code#=1234&#company#=聚合数据'
); //测试阶段,不发短信,直接设置一个“发送成功” json 字符串
$content = $this->juhecurl(C("SEND_SMS_URL") ,$smsConf, 1); //请求发送短信
//$content = json_encode(array('error_code'=>0, 'reason'=>'发送成功'));
if($content){
$result = json_decode($content,true);
$error_code = $result['error_code'];
if($error_code == 0){
// 状态为0,说明短信发送成功
// 数据库存储发送记录,用于处理倒计时和输入验证,首先要删除旧记录
$Record->where("mobile=" . $mobile)->delete();
$data = array(
'mobile' => $mobile,
'tpl_id'=> $tpl_id,
'code'=>$code,
'time'=>time()
);
$Record->data($data)->add();
//echo "短信发送成功,短信ID:".$result['result']['sid'];
}else{
//状态非0,说明失败
//echo "短信发送失败(".$error_code."):".$msg;
}
}else{
//返回内容异常,以下可根据业务逻辑自行修改
//$result['reason'] = '短信发送失败';
}
echo $content;
}
/**
* +--------------------------------------------------------------------------
* 检查填写的手机验证码是否填写正确
* 可以添加更多字段改造成注册、登录等表单
*
* @param string $get.verify 验证码
* @param string $get.mobile 手机号码
* @param int $get.tplid 短信模板ID
* @param int $get.code 手机接收到的验证码
* +--------------------------------------------------------------------------
*/
public function checkSmsCode(){
$verify = I("get.verify");
$tpl_id = I("get.tplid"); // 短信模板id:注册 5596 找回密码 5602 在线核名 5603
$mobile = I("get.mobile"); // 手机号码
$code = I("get.code"); // 手机收到的验证码
if(!$this->check_verify($verify)){
$content = array('resultcode'=>1000, 'reason'=>'验证码填写错误');
echo json_encode($content);
exit();
}
// 检查数据库记录,输入的手机验证码是否和之前通过短信 API 发送到手机的一致
$Record = M("smsrecord");
$where = array(
'mobile' => $mobile,
'tpl_id' => $tpl_id,
'code' => $code,
);
$sms_record = $Record->where($where)->find();
if($sms_record){
echo json_encode(array('reason'=>'短信验证码核对成功'));
// 处理后面的程序(如继续登录、注册等)
}else{
echo json_encode(array('reason'=>'短信验证码错误'));
}
}

最后是企业核名

因为这个接口本来只提供了每次查询一个关键词,而朋友的网站要求能每次查询用“,”分隔的多个关键词,因此需要对提交的数据和返回到前端的进行一番处理(循环处理多个列表)。

前端代码比较简单

<h1>企业核名</h1>
<div id="company-module">
<p>
省份:上海
<input type="hidden" name="company-province" id="company-province" value="SH">
</p>
<p>
<input type="text" name="company-name" id="company-name">
</p>
</div>
<button id="btn-company" type="button" class="btn btn-default">企业核名</button>
<p>公司查询列表:</p>
<ul id="company-result"> </ul>
<javascript 略……
//企业核名(可输入多个以逗号分隔的名称来多次查询)
$("#btn-company").click(function(event) {
$("#reason").html("");
$("#company-result").html("");
// 更新验证码
$("#verify-img").attr('src', '/?m=Home&c=Index&a=verify' + "&time=" + new Date().getTime());
$.getJSON(
'/?m=Home&c=Index&a=getCompanyName',
{
province: $("#company-province").val(),
companyName: $("#company-name").val(),
verify: $("#verify").val(),
},
function(json, textStatus) {
if(json['reason']){
$("#reason").html(json['reason']);
} else {
//console.log(json);
var json_list = JSON.parse(json);
if (json_list.length > 0){
for(i in json_list){
var result_list = json_list[i].Result;
if (result_list.length > 0){
for(j in result_list){
//console.log(result_list[j]);
$("#company-result").append("<li> 名称:" + result_list[j].Name + ", 法人:" + result_list[j].OperName + ", 状态:" + result_list[j].Status + "</li>");
}
}
}
}
}
});
});
</javascript>

后端代码

/**
* +--------------------------------------------------------------------------
* 企业核名
* 该接口 http://eci.yjapi.com/ECIFast/Search 仅支持 GET 方式,因此 $param 为字符串形式
*
* @param string $get.province 省份
* @param string $get.companyName 公司名
* @return json
* +--------------------------------------------------------------------------
*/
public function getCompanyName(){
// 传入 get 参数
$province = I("get.province");
$companyName = I("get.companyName");
$verify = I("get.verify");
// 处理验证码
if ( !$this->check_verify($verify) ) {
$content = array('resultcode'=>1000, 'reason'=>'验证码填写错误');
echo json_encode($content);
exit();
}
// 处理机器人程序刷接口(目前通过IP判断)
$ip = get_client_ip(0, true);
$Record = M("companyrecord");
$company_record = $Record->where("ip='" . $ip . "'")->find();
// if( $company_record && ( (time() - $company_record['time']) < 60 ) ){
// echo json_encode(array('reason'=>'60秒内只能查询一次企业名称'));
// exit();
// }
$resultArray = array();
if ( $province && $companyName ) {
// 删除旧记录(如果有),然后添加新的记录
$Record->where("ip='" . $ip . "'")->delete();
// 循环处理多个公司名
$companies = explode(",", $companyName);
foreach ($companies as $key => $value) {
$params = "key=" . C("COMPANY_KEY") . "&province={$province}&companyName={$value}";
// 开发测试阶段直接返回值,不请求 API
$content = $this->juhecurl(C("COMPANY_URL"), $params, 0);
$returnArray = json_decode($content,true);
// 循环插入新的结果
$resultArray[] = $returnArray;
//$content = array('resultcode'=>200, 'reason'=>'查询成功', 'result'=>array('list'=>array()));
}
$data = array(
'ip' => $ip,
'time'=>time()
);
$Record->add($data);
$content = json_encode($resultArray, true);
echo json_encode($content, true);
}
}

结束

至此三个功能都已经完成了,但是在防止恶意用户利用接口干坏事的策略上,还可以更进一步。例如

  • 必须要注册用户才能发送请求
  • 手机号码每天只能限制发送有限的验证码(因为目前即使每分钟发送一次,一天下来也比较可观了)
  • 手机号码注册后,再次请求发送验证码时,只能发给“已有”的手机号码数据表里的手机号码,而不能把“找回密码”发给一个还没注册的人。

使用聚合数据API查询快递数据-短信验证码-企业核名的更多相关文章

  1. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  2. 功能:使用QQ号登陆,并加上微信和短信提醒,是否增量备份可选,阿里大鱼短信发送开发与测试,聚合数据(用JSON发短信,比较清楚)

    微博就可以,所以其它软件也可以http://desktop.weibo.com/ http://blog.csdn.net/jueblog/article/details/14497181http:/ ...

  3. Android 项目开发实战:聚合数据短信验证码

    聚合数据集成短信验证码官网: https://www.juhe.cn/docs/api/id/54 我根据文档集成了一个例子 效果: 源码下载:http://download.csdn.net/det ...

  4. day102:MoFang:后端完成对短信验证码的校验&基于celery完成异步短信发送&flask_jwt_extended&用户登录的API接口

    目录 1.用户注册 1.后端完成对短信验证码的校验 2.基于celery实现短信异步发送 2.用户登录 1.jwt登录验证:flask_jwt_extended 2.服务端提供用户登录的API接口 1 ...

  5. flask开发restful api系列(5)-短信验证码

    我们现在开发app,注册用户的时候,不再像web一样,发送到个人邮箱了,毕竟个人邮箱在移动端填写验证都很麻烦,一般都采用短信验证码的方式.今天我们就讲讲这方面的内容. 首先,先找一个平台吧.我们公司找 ...

  6. 短信API——短信验证码

    简介 短信服务(Short Message Service.SMS)是指通过调用短信发送API,将指定短信内容发送给指定手机用户. 阿里云短信服务 阿里云短信服务产品介绍:https://www.al ...

  7. 短信验证码api

    最近遇到的项目需要个随机短信验证码实现注册用户 选用的是“云信使”,因为有15条免费的测试短信可以验证代码是否正确调用该短信api 地址 进入短信平台 一.实名认证 + 短信模板 用户认证完成后,创建 ...

  8. Android开发之短信验证码示例

    在说Android中的短信验证码这个知识点前,我们首先来了解下聚合数据 聚合数据介绍 聚合数据是一家国内最大的基础数据API提供商,专业从事互联网数据服务.免费提供从天气查询.空气质量.地图坐标到金融 ...

  9. vue_drf之实现短信验证码

    一.需求 1,需求 我们在做网站开发时,登录页面很多情况下是可以用手机号接收短信验证码,然后实现登录的,那我们今天就来做一做这一功能. 伪代码: 进入登录页面,点击短信登录 输入手机号码,点击获取验证 ...

随机推荐

  1. 【转】手动写一个Behavior Designer任务节点

    http://blog.csdn.net/qq_33747722/article/details/53539532 自己手写一个类似于CanSeeObject.Seek等任务节点并不是一件难事 下面我 ...

  2. 【bzoj4896】[Thu Summer Camp2016]补退选 Trie树+STL-vector

    题目描述 X是T大的一名老师,每年他都要教授许多学生基础的C++知识.在T大,每个学生在每学期的开学前都需要选课,每次选课一共分为三个阶段:预选,正选,补退选:其中"补退选"阶段最 ...

  3. CLion 使用笔记(三)

    我已经在博客里面发布了好几篇 CLion 使用笔记了,没追究这是第几篇,姑且算作第三篇. 我的 CLion 是搭配了 MSYS2 和 Conan 使用的.MSYS2 提供 C++ toolchain. ...

  4. webRTC前世今生

    WebRTC 的前世今生 本文由 rwebrtc 翻译 WebRTC 技术是激烈的开放的 Web 战争中一大突破.-Brendan Eich, inventor of JavaScript 无插件实时 ...

  5. 0-Broadcast机制原理简要介绍

    Broadcast机制简要介绍 来源: http://blog.csdn.net/luoshengyang/article/details/6730748 导语 广播机制在Android系统中,也不算 ...

  6. pat 甲级 Cars on Campus (30)

    Cars on Campus (30) 时间限制 1000 ms 内存限制 65536 KB 代码长度限制 100 KB 判断程序 Standard  题目描述 Zhejiang University ...

  7. COGS 2485. [HZOI 2016]从零开始的序列

    2485. [HZOI 2016]从零开始的序列 ★★   输入文件:sky_seq.in   输出文件:sky_seq.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] ...

  8. .NET获取URL的各种方式及其区别

    原文发布时间为:2009-11-11 -- 来源于本人的百度文章 [由搬家工具导入] http://www.test.com/testweb/default.aspx?id=1 Request.App ...

  9. C#Url传递中文参数时解决方法

    原文发布时间为:2008-11-05 -- 来源于本人的百度文章 [由搬家工具导入] 1.设置web.config文件。<system.web> <globalization req ...

  10. PowerDesigner 中将Comment(注释)及Name(名称)内容互相COPY的VBS代码

    在用PowerDesigner时.常常在NAME或Comment中写中文在Code中写英文.Name只会显示给我们看,Code会使用在代码中.但Comment中的文字会保存到数据库TABLE的Desc ...