[源码下载]

重新想象 Windows 8 Store Apps (61) - 通信: http, oauth

作者:webabcd

介绍
重新想象 Windows 8 Store Apps 之 通信

  • HttpClient 概述
  • http get string
  • http get stream
  • http post string
  • http post stream
  • OAuth 2.0 验证的客户端

示例
用于演示 http 通信的服务端
WebServer/HttpDemo.aspx.cs

/*
* 用于响应 http 请求
*/ using System;
using System.IO;
using System.Threading; namespace WebServer
{
public partial class HttpDemo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 停 3 秒,以方便测试 http 请求的取消
Thread.Sleep(); var action = Request.QueryString["action"]; switch (action)
{
case "getString": // 响应 http get string
Response.Write("hello webabcd");
break;
case "getStream": // 响应 http get stream
Response.Write("hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd hello webabcd");
break;
case "postString": // 响应 http post string
Response.Write(string.Format("param1:{0}, param2:{1}, referrer:{2}", Request.Form["param1"], Request.Form["param2"], Request.UrlReferrer));
break;
case "postStream": // 响应 http post stream
using (StreamReader reader = new StreamReader(Request.InputStream))
{
string body = reader.ReadToEnd();
Response.Write(Server.HtmlEncode(body));
}
break;
default:
break;
} Response.End();
}
}
}

1、通过 HttpClient, HttpRequestMessage, HttpResponseMessage 实现 HTTP 通信
Communication/HTTP/Summary.xaml

<Page
x:Class="XamlDemo.Communication.HTTP.Summary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Communication.HTTP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> <Button Name="btnPost" Content="http post" Click="btnPost_Click_1" Margin="0 10 0 0" /> <Button Name="btnCancel" Content="cancel" Click="btnCancel_Click_1" Margin="0 10 0 0" /> </StackPanel>
</Grid>
</Page>

Communication/HTTP/Summary.xaml.cs

/*
* 通过 HttpClient, HttpRequestMessage, HttpResponseMessage 实现 HTTP 通信
*
* HttpClient - 用于发起 http 请求,以及接收 http 响应
* BaseAddress - 发送请求的 uri
* DefaultRequestHeaders - 默认的 http 请求头信息
* MaxResponseContentBufferSize - 读取响应内容时,所可以缓冲的最大字节数。默认值:64K
* Timeout - http 请求的超时时间
* CancelPendingRequests() - 取消该 HttpClient 对象所有挂起的 http 请求
* GetStringAsync(), GetStreamAsync(), GetByteArrayAsync(), GetAsync() - http get 数据
* PostAsync(), DeleteAsync(), PutAsync() - http post delete put 数据
* 参数:HttpContent content - http 请求的数据(HttpContent 类型)
* 继承自 HttpContent 的类有:StringContent, ByteArrayContent, StreamContent, FormUrlEncodedContent 等
* 参数:HttpCompletionOption completionOption(HttpCompletionOption 枚举)
* ResponseContentRead - 获取到全部内容后再返回数据,默认值
* ResponseHeadersRead - 获取到头信息后就返回数据,用于流式获取
*
* HttpRequestMessage - http 请求
* Method - http 方法
* RequestUri - 请求的 uri
* Version - http 版本,默认是 1.1
* Headers - http 的请求头信息
* Content - http 请求的内容(HttpContent 类型)
* 继承自 HttpContent 的类有:StringContent, ByteArrayContent, StreamContent, FormUrlEncodedContent 等
*
* HttpResponseMessage - http 响应
* RequestMessage - 对应的 HttpRequestMessage 对象
* Headers - http 的响应头信息
* Version - http 版本,默认是 1.1
* StatusCode - http 响应的状态码
* ReasonPhrase - http 响应的状态码所对应的短语
* IsSuccessStatusCode - http 响应的状态码是否是成功的值(200-299)
* EnsureSuccessStatusCode() - 当 IsSuccessStatusCode 为 false 时会抛出异常
*
*
* 注:关于下载/上传的进度获取,请参见“后台任务”
*
* 另:win8 metro 的 http 抓包可用 fiddler
*
* 还有:
* http 通信还可以通过如下方法实现
* HttpWebRequest webRequest = WebRequest.Create(url);
*/ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Communication.HTTP
{
public sealed partial class Summary : Page
{
private HttpClient _httpClient; public Summary()
{
this.InitializeComponent();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// 释放资源
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
} private async void btnPost_Click_1(object sender, RoutedEventArgs e)
{
_httpClient = new HttpClient(); try
{
string url = "http://localhost:39629/HttpDemo.aspx?action=postString";
// 创建一个 HttpRequestMessage 对象
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url); // 需要 post 的数据
var postData = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("param1", "web"),
new KeyValuePair<string, string>("param2", "abcd")
}
); // http 请求的数据
request.Content = postData;
// http 请求的头信息
request.Headers.Referrer = new Uri("http://webabcd.cnblogs.com"); // 请求 HttpRequestMessage 对象,并返回 HttpResponseMessage 数据
HttpResponseMessage response = await _httpClient.SendAsync(request); // http 响应的状态码及其对应的短语
lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
lblMsg.Text += Environment.NewLine; // 以字符串的方式获取响应数据
lblMsg.Text += await response.Content.ReadAsStringAsync();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException)
{
lblMsg.Text += "取消了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
// 取消 http 请求
_httpClient.CancelPendingRequests();
}
}
}

2、演示 http get string
Communication/HTTP/GetString.xaml.cs

/*
* 演示 http get string
*/ using System;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Communication.HTTP
{
public sealed partial class GetString : Page
{
private HttpClient _httpClient; public GetString()
{
this.InitializeComponent();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// 释放资源
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
} private async void btnGetString_Click_1(object sender, RoutedEventArgs e)
{
_httpClient = new HttpClient(); try
{
HttpResponseMessage response = await _httpClient.GetAsync(new Uri("http://localhost:39629/HttpDemo.aspx?action=getString")); lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
lblMsg.Text += Environment.NewLine; // HttpContent.ReadAsStringAsync() - 以 string 方式获取响应数据
// HttpContent.ReadAsByteArrayAsync() - 以 byte[] 方式获取响应数据
// HttpContent.ReadAsStreamAsync() - 以 stream 方式获取响应数据
lblMsg.Text += await response.Content.ReadAsStringAsync();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException)
{
lblMsg.Text += "取消了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
// 取消 http 请求
_httpClient.CancelPendingRequests();
}
}
}

3、演示 http get stream
Communication/HTTP/GetStream.xaml.cs

/*
* 演示 http get stream
*/ using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.Security.Cryptography;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Communication.HTTP
{
public sealed partial class GetStream : Page
{
private HttpClient _httpClient; public GetStream()
{
this.InitializeComponent();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// 释放资源
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
} private async void btnGetStream_Click_1(object sender, RoutedEventArgs e)
{
_httpClient = new HttpClient(); try
{
// HttpCompletionOption.ResponseHeadersRead - 获取到头信息后就返回数据,用于流式获取
HttpResponseMessage response = await _httpClient.GetAsync(
new Uri("http://localhost:39629/HttpDemo.aspx?action=getStream"),
HttpCompletionOption.ResponseHeadersRead); lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
lblMsg.Text += Environment.NewLine; // HttpContent.ReadAsStringAsync() - 以 string 方式获取响应数据
// HttpContent.ReadAsByteArrayAsync() - 以 byte[] 方式获取响应数据
// HttpContent.ReadAsStreamAsync() - 以 stream 方式获取响应数据
using (Stream responseStream = await response.Content.ReadAsStreamAsync())
{
byte[] buffer = new byte[];
int read = ; while ((read = await responseStream.ReadAsync(buffer, , buffer.Length)) > )
{
lblMsg.Text += "读取的字节数: " + read.ToString();
lblMsg.Text += Environment.NewLine; IBuffer responseBuffer = CryptographicBuffer.CreateFromByteArray(buffer);
lblMsg.Text += CryptographicBuffer.EncodeToHexString(responseBuffer);
lblMsg.Text += Environment.NewLine; buffer = new byte[];
}
}
}
catch (TaskCanceledException)
{
lblMsg.Text += "取消了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
// 取消 http 请求
_httpClient.CancelPendingRequests();
}
}
}

4、演示 http post string
Communication/HTTP/PostString.xaml.cs

/*
* 演示 http post string
*/ using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Communication.HTTP
{
public sealed partial class PostString : Page
{
private HttpClient _httpClient; public PostString()
{
this.InitializeComponent();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// 释放资源
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
} private async void btnPostString_Click_1(object sender, RoutedEventArgs e)
{
_httpClient = new HttpClient(); try
{
// 需要 post 的数据
var postData = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("param1", "web"),
new KeyValuePair<string, string>("param2", "abcd")
}
); HttpResponseMessage response = await _httpClient.PostAsync(
new Uri("http://localhost:39629/HttpDemo.aspx?action=postString"),
postData); lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
lblMsg.Text += Environment.NewLine; // HttpContent.ReadAsStringAsync() - 以 string 方式获取响应数据
// HttpContent.ReadAsByteArrayAsync() - 以 byte[] 方式获取响应数据
// HttpContent.ReadAsStreamAsync() - 以 stream 方式获取响应数据
lblMsg.Text += await response.Content.ReadAsStringAsync();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException)
{
lblMsg.Text += "取消了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
// 取消 http 请求
_httpClient.CancelPendingRequests();
}
}
}

5、演示 http post stream
Communication/HTTP/PostStream.xaml.cs

/*
* 演示 http post stream
*/ using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Communication.HTTP
{
public sealed partial class PostStream : Page
{
private HttpClient _httpClient; public PostStream()
{
this.InitializeComponent();
} protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// 释放资源
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
} private async void btnPostStream_Click_1(object sender, RoutedEventArgs e)
{
_httpClient = new HttpClient(); try
{
// 需要 post 的 stream 数据
Stream stream = GenerateSampleStream();
StreamContent streamContent = new StreamContent(stream); HttpResponseMessage response = await _httpClient.PostAsync(
new Uri("http://localhost:39629/HttpDemo.aspx?action=postStream"),
streamContent); lblMsg.Text += ((int)response.StatusCode) + " " + response.ReasonPhrase;
lblMsg.Text += Environment.NewLine; // HttpContent.ReadAsStringAsync() - 以 string 方式获取响应数据
// HttpContent.ReadAsByteArrayAsync() - 以 byte[] 方式获取响应数据
// HttpContent.ReadAsStreamAsync() - 以 stream 方式获取响应数据
lblMsg.Text += await response.Content.ReadAsStringAsync();
lblMsg.Text += Environment.NewLine;
}
catch (TaskCanceledException)
{
lblMsg.Text += "取消了";
lblMsg.Text += Environment.NewLine;
}
catch (Exception ex)
{
lblMsg.Text += ex.ToString();
lblMsg.Text += Environment.NewLine;
}
} // 生成一个指定大小的内存流
private static MemoryStream GenerateSampleStream(int size)
{
byte[] subData = new byte[size];
for (int i = ; i < subData.Length; i++)
{
subData[i] = (byte)( + i % ); // a-z
} return new MemoryStream(subData);
} private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
// 取消 http 请求
_httpClient.CancelPendingRequests();
}
}
}

6、演示如何开发一个基于 OAuth 2.0 验证的客户端
Communication/OpenAuth/ClientDemo.xaml

<Page
x:Class="XamlDemo.Communication.OpenAuth.ClientDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:XamlDemo.Communication.OpenAuth"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="Transparent">
<StackPanel Margin="120 0 0 0"> <Button Name="btnWeibo" Content="登录新浪微博,并返回登录用户好友最新发布的微博" Click="btnWeibo_Click" /> <TextBlock Name="lblMsg" FontSize="14.667" TextWrapping="Wrap" Margin="0 10 0 0" /> </StackPanel>
</Grid>
</Page>

Communication/OpenAuth/ClientDemo.xaml.cs

/*
* 演示如何开发一个基于 OAuth 2.0 验证的客户端
*
* WebAuthenticationBroker - 用于 OAuth 2.0 验证的第一步,可以将第三方 UI 无缝整合进 app
* AuthenticateAsync(WebAuthenticationOptions options, Uri requestUri, Uri callbackUri) - 请求 authorization code,返回一个 WebAuthenticationResult 类型的数据
*
* WebAuthenticationResult - 请求 authorization code(OAuth 2.0 验证的第一步)的结果
* ResponseData - 响应的数据
* ResponseStatus - 响应的状态
*
*
* 关于 OAuth 2.0 协议参见:http://tools.ietf.org/html/draft-ietf-oauth-v2-20
*/ using System;
using System.Net.Http;
using System.Text.RegularExpressions;
using Windows.Data.Json;
using Windows.Security.Authentication.Web;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls; namespace XamlDemo.Communication.OpenAuth
{
public sealed partial class ClientDemo : Page
{
public ClientDemo()
{
this.InitializeComponent();
} private async void btnWeibo_Click(object sender, RoutedEventArgs e)
{
try
{
var appKey = "";
var appSecret = "652ec0b02f814d514fc288f3eab2efda";
var callbackUrl = "http://webabcd.cnblogs.com"; // 在新浪微博开放平台设置的回调页 var requestAuthorizationCode_url =
string.Format("https://api.weibo.com/oauth2/authorize?client_id={0}&response_type=code&redirect_uri={1}",
appKey,
callbackUrl); // 第一步:request authorization code
WebAuthenticationResult WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri(requestAuthorizationCode_url),
new Uri(callbackUrl)); // 第一步的结果
lblMsg.Text = WebAuthenticationResult.ResponseStatus.ToString() + Environment.NewLine; if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
{
// 从第一步返回的数据中获取 authorization code
var authorizationCode = QueryString(WebAuthenticationResult.ResponseData, "code");
lblMsg.Text += "authorizationCode: " + authorizationCode + Environment.NewLine; var requestAccessToken_url =
string.Format("https://api.weibo.com/oauth2/access_token?client_id={0}&client_secret={1}&grant_type=authorization_code&redirect_uri={2}&code={3}",
appKey,
appSecret,
callbackUrl,
authorizationCode); // 第二步:request access token
HttpClient client = new HttpClient();
var response = await client.PostAsync(new Uri(requestAccessToken_url), null); // 第二步的结果:获取其中的 access token
var jsonString = await response.Content.ReadAsStringAsync();
JsonObject jsonObject = JsonObject.Parse(jsonString);
var accessToken = jsonObject["access_token"].GetString();
lblMsg.Text += "accessToken: " + accessToken + Environment.NewLine; var requestProtectedResource_url =
string.Format("https://api.weibo.com/2/statuses/friends_timeline.json?access_token={0}",
accessToken); // 第三步:request protected resource,获取需要的数据(本例为获取登录用户好友最新发布的微博)
var result = await client.GetStringAsync(new Uri(requestProtectedResource_url));
lblMsg.Text += "result: " + result;
}
}
catch (Exception ex)
{
lblMsg.Text += Environment.NewLine;
lblMsg.Text += ex.ToString(); // 由于本 app 没有提交新浪微博开放平台审核,所以需要在新浪微博开放平台中添加测试账号,否则会出现异常
}
} /// <summary>
/// 模拟 QueryString 的实现
/// </summary>
/// <param name="queryString">query 字符串</param>
/// <param name="key">key</param>
private string QueryString(string queryString, string key)
{
return Regex.Match(queryString, string.Format(@"(?<=(\&|\?|^)({0})\=).*?(?=\&|$)", key), RegexOptions.IgnoreCase).Value;
}
}
} /*
* OAuth 2.0 的 Protocol Flow
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
*/

OK
[源码下载]

重新想象 Windows 8 Store Apps (61) - 通信: http, oauth的更多相关文章

  1. 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化

    [源码下载] 重新想象 Windows 8 Store Apps (60) - 通信: 获取网络信息, 序列化和反序列化 作者:webabcd 介绍重新想象 Windows 8 Store Apps ...

  2. 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP

    [源码下载] 重新想象 Windows 8 Store Apps (62) - 通信: Socket TCP, Socket UDP 作者:webabcd 介绍重新想象 Windows 8 Store ...

  3. 重新想象 Windows 8 Store Apps (63) - 通信: WebSocket

    [源码下载] 重新想象 Windows 8 Store Apps (63) - 通信: WebSocket 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通信 So ...

  4. 重新想象 Windows 8 Store Apps 系列文章索引

    [源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...

  5. 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传

    [源码下载] 重新想象 Windows 8 Store Apps (66) - 后台任务: 下载和上传 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 后台任务 后台 ...

  6. 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel)

    [源码下载] 重新想象 Windows 8 Store Apps (68) - 后台任务: 控制通道(ControlChannel) 作者:webabcd 介绍重新想象 Windows 8 Store ...

  7. 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo

    [源码下载] 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo 作者:webabcd 介绍重新想象 Wind ...

  8. 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解

    [源码下载] 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Toa ...

  9. 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解

    [源码下载] 重新想象 Windows 8 Store Apps (36) - 通知: Tile 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Tile ...

随机推荐

  1. LeetCode: Convert Sorted List to Binary Search Tree 解题报告

    Convert Sorted List to Binary Search Tree Given a singly linked list where elements are sorted in as ...

  2. 项目管理知识体系指南(PMBOOK指南)(第5版) 阅读摘要

    1.7.2 项目经理的人际技能 领导力: 团队建设: 激励: 沟通: 影响力: 决策能力: 政治和文化意识: 谈判: 建立信任: 冲突管理: 教练技术: 3.4 规划过程组 在制定项目管理计划和项目文 ...

  3. Xcode工程使用CocoaPods管理第三方库新建工程时出现错误

    工程使用CocoaPods管理第三方库,在新的目录update版本的时候出现如下问题   问题1描述: diff: /../Podfile.lock: No such file or director ...

  4. Subgradient Algorithm

    Subgradient是一种可以优化不可微的凸函数的方法. 首先回顾凸函数的定义: $f(y) \geq f(x) + \nabla f(x)^T(y-x), all \hspace{2 pt} x, ...

  5. Unix sed实用教程系列目录[已完成]

    本系列文章已经译完了,译自awk-sed@theunixschool,收获颇丰,作者没有讲明白的我做了补充,并且尝试讲的更清楚,整理成系列索引,方便学习,开篇非译文,是我为了方便后面的理解写的一篇,感 ...

  6. Git使用总结

    一.Git的特性 Speed 速度(git是用c语言写的.一般都是提交到本地) Simple design Strong support for non-linear development (tho ...

  7. 如何生成ipa文件

    xcode--Product--Archive 弹出Organizer-Archives选择Distribute---Save for EnterPrise or Ad_Hoc Deployment- ...

  8. 详解shape标签

    转载自:http://blog.csdn.net/harvic880925/article/details/41850723 一.简单使用 刚开始,就先不讲一堆标签的意义及用法,先简单看看shape标 ...

  9. Docker练习例子:基于 VNCServer + noVNC 构建 Docker 桌面系统

    0. 安装docker 这一步略,网上有好多教程,一般出现装不上的原因,也就是网速问题了,这个我也很难帮你. 1. 下载指定的镜像images docker pull dorowu/ubuntu-de ...

  10. 同时支持控制台和MFC窗口程序的APP

    BOOL CMyApp::InitInstance() { if ( m_bShowGui==FALSE ) { FILE *stream = NULL; AllocConsole(); // 开辟控 ...