Hex To ASCII Converter: http://www.aooshi.org/tools/hex2ascii.html
.
命令目录:
dotnet-new
dotnet-restore
dotnet-run
dotnet-build
dotnet-test
dotnet-pack
dotnet-publish
现在来详细讲解。
首先我们创建一个项目 ,这里我们创建控制台程序。
dotnet new
dotnet 更多命令请参考帮助。
我们在创建一个 class lib 也就是类库。
dotnet new -t lib
创建好以后,编写一些自己的代码然后进行打包。
我编写了两个方法,现在来打包。
dotnet restore
dotnet pack
.NET Core 怎样添加离线引用包呢?现在答案就揭晓了。
打包好以后,我们将applib 添加到 app的 project.json 。
添加好以后切到app 目录,然后进行还原。
还原使用的命令是:dotnet restore -f E:\dotnet\applib\bin\Debug\
dotnet restore -f 包的路径
这样我们就能直接在项目里调用applib 里面的方法。
我们在代码里编写对应的调用,然后执行程序。可以看到正确输出class lib 的结果。
以app 为例:
dotnet build 编译代码
dotnet run 执行程序
dotnet xx.dll 也是执行程序
这里我们要新建一个文件夹及项目了。
新建测试项目: dotnet new -t xunittest
新建好项目我们可以在里面添加测试方法,这里我直接运行测试。
dotnet restore
dotnet test
重点来了,发布项目使其可以跨平台运行。
dotnet publish 默认发布
发布后定位到publish目录使用 dotnet xx.dll 执行应用。
下面来跨平台发布。
可以参考我之前的文章:http://www.cnblogs.com/linezero/p/5475246.html
在 project.json 加入 runtimes 节点 注释掉 "type": "platform"。
首先我们要dotnet restore
这里我还原的时候有些久,大家耐心等待一下。
dotnet publish -r win10-x64
这里发布后,可以直接定位到发布publish目录,执行 app.exe 即可。
dotnet publish -r ubuntu.14.04-x64
将publish 文件夹上传至linux系统 ,设置app的权限为可执行,然后 ./app 就可以运行了。
dotnet publish -r 指定runtimes节点里系统ID
.
转自: http://www.cnblogs.com/linezero/p/dotnet.html
参考: https://docs.microsoft.com/en-us/dotnet/articles/core/tools/index
历史
回车”(Carriage Return)和“换行”(Line Feed)这两个概念的来历和区别。
符号 ASCII码 意义
\n 10 换行
\r 13 回车CR
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33,Linux/Unix下的tty概念也来自于此)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正 好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。
后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。
在Windows中:
'\r' 回车,回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
'\n' 换行,换到当前位置的下一行,而不会回到行首;
Unix系统里,每行结尾只有“<换行>”,即"\n";Windows系统里面,每行结尾是“<回车><换 行>”,即“\r\n”;Mac系统里,每行结尾是“<回车>”,即"\r";。一个直接后果是,Unix/Mac系统下的文件在 Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。
例:
$ echo -en '12\n34\r56\n\r78\r\n' > tmp.txt
分别在Windws和Linux中查看此文件可知:
Linux中遇到换行符("\n")会进行回车+换行的操作,回车符反而只会作为控制字符("^M")显示,不发生回车的操作。而windows中要回车符+换行符("\r\n")才会回车+换行,缺少一个控制符或者顺序不对都不能正确的另起一行。
IE中 IFRAME,JSONP 跨域 COOKIE
P3P: CP=CAO PSA OUR
参考表:
浏览器 | 默认允许第三方Cookie | 是否支持P3P | 禁止第三方Cookie后,配置P3P简明策略头的效果 | 补充 |
IE6 | 否 | 是 |
HTTP可读写Cookie (第二次.直接Cache.也不行.除非第一次非Cache并读到p3p头.后面我会提到解决方案.) |
避免JS的写操作 |
IE7-IE9
|
否 | 是 | HTTP、JS,可随意读写. | - |
FireFox | 是 | 否 | HTTP、JS都不可读写 | - |
Chrome | 是 | 部分支持,趋势-否 | 趋势为HTTP、JS可读不可写. | - |
Safari | 否 | 否 | HTTP、JS可读不可写 | 借助Post提交表单,实现写操作. |
Opera | 是 |
否
|
JS可读写 HTTP可读不可写. |
- |
相关资源: http://www.w3.org/2002/04/P3Pv1-header.html
Compact Policies(简洁策略)
简洁策略,本质上就是P3P策略的一个摘要. 他们的作用是,使用户代理,可以快速敏捷的获取到站点的P3P策略信息,所以是对性能有益的.
为了深入的解释简洁策略,按照 P3P1.0[4]规范,我们列出下面这些限制性的语法:
compact-policy-field = `CP="` compact-policy `"`
compact-policy = compact-token *(" " compact-token)
compact-token = compact-access |
compact-disputes |
compact-remedies |
compact-non-identifiable |
compact-purpose |
compact-recipient |
compact-retention |
compact-categories |
compact-test
compact-access = "NOI" | "ALL" | "CAO" | "IDC" | "OTI" | "NON"
compact-disputes = "DSP"
compact-remedies = "COR" | "MON" | "LAW"
compact-non-identifiable = "NID"
compact-purpose = "CUR" | "ADM" [creq] | "DEV" [creq] | "TAI" [creq] |
"PSA" [creq] | "PSD" [creq] | "IVA" [creq] | "IVD" [creq] |
"CON" [creq] | "HIS" [creq] | "TEL" [creq] | "OTP" [creq]
creq = "a" | "i" | "o"
compact-recipient = "OUR" | "DEL" [creq] | "SAM" [creq] | "UNR" [creq] |
"PUB" [creq] | "OTR" [creq]
compact-retention = "NOR" | "STP" | "LEG" | "BUS" | "IND"
compact-category = "PHY" | "ONL" | "UNI" | "PUR" | "FIN" | "COM" |
"NAV" | "INT" | "DEM" | "CNT" | "STA" | "POL" |
"HEA" | "PRE" | "LOC" | "GOV" | "OTC"
compact-test = "TST"
常用的简洁策略的 P3P头为 - P3P : CP=CAO PSA OUR (其实, CP=. 就可以了.或者其他任何值都是可以的)分别对应了 :
compact-access(访问) : CAO - contact-and-other
Identified Contact Information and Other Identified Data: access is given to identified online and physical contact information as well as to certain other identified data.
直译 : 被识别的联系信息,和其他被识别的数据: 网上,或现实中的联系信息,和某些被识别的数据,允许被访问.
我的理解: 应该是, 允许被确认的信息和数据的访问. (允许第三方cookie的读写)
compact-purpose(目的) : PSA - pseudo-analysis .身份验证、分析
compact-recipient(受体) : OUR - ours
Ourselves and/or entities acting as our agents or entities for whom we are acting as an agent: An agent in this instance is defined as a third party that processes data only on behalf of the service provider for the completion of the stated purposes. (e.g., the service provider and its printing bureau which prints address labels and does nothing further with the information
直译 : 我们自己,以及(或)实体作为我们自己的代理,或被我们所代理方的实体:这种情况下的代理,被定义为,相关进程数据,代表服务提供者,用来完成其所设定服务的,第三方.(就好像,一个印刷局作为提供打印服务的,服务提供者,其只负责打印标签神马的,但是却不会进一步,对相关的信息,做任何事情 )
备注:
. IE P3P简洁策略,可以最简写成: P3P:CP=.
. 对于第三方来说,建议避免使用JS操作Cookie,最多用来读,而不是写. 除非是和登录验证有关,否则建议使用Storage代替Cookie的使用.
参考:
1. http://p3ptoolbox.org/tools/
2. http://www.w3.org/P3P/implementations/
3. http://www.w3.org/P3P/
4. http://www.w3.org/TR/2002/REC-P3P-20020416/
5. https://www.w3.org/2002/04/P3Pv1-header.html
6.Validate at: http://www.w3.org/P3P/validator.html
7.Learn more at: http://www.fiddler2.com/redir/?id=p3pinfo
8. http://www.w3.org/P3P/details.html
搞自 c# 7.0展望
C# 2.0 引入泛型。
C# 3.0 通过扩展方法、lambda表达式、匿名类型和其他相关特性带来了LINQ。
C# 4.0 都是关于与动态非强类型语言的互操作。
C# 5.0 简化异步编程和异步等待等关键词。
C# 6.0 完全重写,并且引入了各种各种更易实现的小特性和改进。你可以在DotNetCurry(DNC)杂志2016年1月版上找到一篇C#6.0特性的概述文章: U升级现有C#代码到 C# 6.0 。
资料来源于阿里, 备份供查阅:
--------------------------------------------
当邮件发送方服务器的IP被国际反垃圾邮件组织屏蔽后解除封锁的步骤首先要做的事:
1、所做测试均在问题服务器上进行。
2、确认问题服务器的IP(或整个IP段)不在SBL、RBL、CBL中
关于国际黑名单查询,您可以在这里:http://www.dnsstuff.com/tools/ip4r.ch?ip=(您的IP) 或http://www.kloth.net/services/dnsbl.php (推荐使用)进行查询。
其他应用范围较广泛的黑名单组织网站:
http://www.spamhaus.org/sbl/index.lasso
http://www.spamhaus.org/xbl/index.lasso
http://www.spamcop.net/bl.shtml
http://anti-spam.org.cn/services/rbl.php
http://www.senderbase.org/search?page=senders
http://openrbl.org/
如果您很不幸的列在上述组织的黑名单中,那您就需要向他们申请解封。(全英文的,填申请资料过程很繁琐)
一般48小时内给予答复,若这个时间内您的邮件服务器依然向外发送垃圾邮件,而他们又接到举报,他们会在1小时之内把您Blocked 掉
3、确认发信域名能够解析,且问题服务器上设置的域名在有效期内并可正常使用。
4、在问题邮件服务器上完成测试
5、查看自己域名的MX记录
6、TELNET命令测试
根据返回的错误代码判断
3.1 错误代码:450 4.7.1 Client host rejected: cannot find your hostname
错误原因:对方服务器未设置反向解析
处理方式:请联络IDC进行处理。
可参考中国互联网协会反垃圾中心提供的设置方式:http://www.anti-spam.cn/ShowArticle.php?id=2269
3.2 错误代码:450 4.7.1 Helo command rejected: Host not found
错误原因:对方服务器在HELO命令中提供的域名不能被解析
处理方式:请检查其HELO命令提供的域名信息,且保证其符合RFC1035国际标准的规定。
3.3 错误代码:504 5.5.2 Helo command rejected: need fully-qualified hostname
错误原因:对方服务器的HELO信息不是完整的域名
处理方式:请检查HELO命令提供的域名信息,且保证其符合RFC1035国际标准的规定。
3.4 错误代码:501 5.5.2 Helo command rejected: Invalid name
错误原因:对方服务器的HELO信息包含非法的字符
处理方式:RFC规定,HELO命令提供的信息不得包含中文字符。
请对方按照RFC1035国际标准规定,对其HELO信息设置进行修改。
3.5 错误代码:554 5.7.1 Recipient address rejected: Dynamic IP
错误原因:对方服务器使用动态IP
处
理方式:请对方查看中华人民共和国信息产业部令第38号《互联网电子邮件服务管理办法》中的第四条:第四条
提供互联网电子邮件服务,应当事先取得增值电信业务经营许可或者依法履行非经营性互联网信息服务备案手续。未取得增值电信业务经营许可或者未履行非经营性
互联网信息服务备案手续,任何组织或者个人不得在中华人民共和国境内开展互联网电子邮件服务。
3.6 错误代码:554 5.7.1 Service unavailable;
错误原因:对方服务器IP被国际权威的反垃圾组织列入黑名单
处理方式:请对方访问http://www.dnsstuff.com/tools/ip4r.ch?ip=查询并申请解封。解封后即恢复正常。
7 最后将退信,TELNET测试结果,已经公司信息等要求的内容发送给相对应的组织,又是用英文邮件,对方如果审核解除后会给您回复邮件,一般您收到邮件后即可恢复正常。
参阅:
Adf.cs
http://www.xiaobo.li/adf/513.html
Adf.RegistryServer
http://www.xiaobo.li/adf/516.html
客户端支持, 配置模式及注册中心模式
两种模式使用方式完全一致,仅配置节定义区别,如下:
配置模式:
<section name="TestServer" type="Adf.Config.IpGroupSection,Adf"/>
注册中心模式:
<section name="TestServer" type="Adf.Cs.CsRegistrySection,Adf.Cs"/>
完整配置参考:
<?xml version="1.0"?> <configuration> <configSections> <section name="TestServer" type="Adf.Config.IpGroupSection,Adf"/> <!--<section name="TestServer" type="Adf.Cs.CsRegistrySection,Adf.Cs"/>--> </configSections> <appSettings> <add key="Log:Path" value="c:\Logs\Adf.Cs\TestClient"/> <!-- 日志刷新时间间隔(秒) --> <add key="Log:FlushInterval" value="10"/> <!-- 日志禁用 --> <!--<add key="Log:Disabled" value="all"/>--> </appSettings> <!-- Servers --> <TestServer> <!--<add ip="127.0.0.1" port="200"/>--> <add ip="127.0.0.2" port="4562"/> <add ip="127.0.0.3" port="4562"/> <add ip="127.0.0.4" port="4562"/> </TestServer> </configuration>
.
应用及安装文章:
http://www.xiaobo.li/adf/516.html
安装完成后,通过以下方式调用:
以此配置为例:
<!-- 服务监听IP,不指定默认本机接口 -->
<add key="ServiceMonitorIp" value="127.0.0.1"/>
<!-- 服务监控端口 -->
<add key="ServiceMonitorPort" value="200"/>
主机地址: http://127.0.0.1:200
注册一个主机到组:
HTTP POST: http://127.0.0.1:200?action=register
POST DATA:
{
"group":"group name", //register group name
"host":"ip",
"port":0
"custom attr1":"" //custom attribute 1
"custom attr2":"" //custom attribute 2
...
"custom attrN":"" //custom attribute N
}
获取一组注册主机:
HTTP GET: http://127.0.0.1:200?action=get&group={group name}
通过 Adf.Service 嵌入,可简单实现一个 .Net 项目的 windows 服务
下载:
Adf.Service http://www.aooshi.org/adf/download/Adf.Service.1.3.zip
源码:
应用:
1. 创建控制台应用程序, 版本2.0或以上
2. 引用: adf.dll, adf.service
3. 修改: Program为共公public访问符
4. Program 继承Adf.Service.IService, Main 函数调用 Adf.Service.ServiceHelper.Entry(args);
5. 建立: app.config 文件,并配置 ServiceMonitorPort
6. 复制 Tool*.bat 并修改Adf.Service.Test为你的应用程序
Program.cs 参考:
using System; using System.Collections.Specialized; namespace Adf.Service.Test { /// <summary> /// 程序入口 /// </summary> public class Program : IService { /// <summary> /// 应用程序的主入口点。 /// </summary> /// <param name="args"></param> static void Main(string[] args) { Adf.Service.ServiceHelper.Entry(args); } public void Initialize(ServiceContext serviceContext) { //注册当前服务至注册中心 //serviceContext.MonitorToRegistry(); } public void Start(ServiceContext serviceContext) { serviceContext.Logger.Message.WriteLine("My Service Start"); } public void Stop(ServiceContext serviceContext) { serviceContext.Logger.Message.WriteLine("My Service Stop"); } public System.Net.HttpStatusCode HttpAction(string action, ServiceContext serviceContext, HttpServerContext httpServerContext) { serviceContext.Logger.Message.WriteLine("httpaction:" + httpServerContext.Url); return System.Net.HttpStatusCode.OK; } public string Status(ServiceContext serviceContext, NameValueCollection queryString) { return string.Empty; } public void Dispose() { } } }
配置参考:
<?xml version="1.0"?> <configuration> <configSections> <section name="cluster" type="Adf.Config.IpGroupSection,Adf"/> <section name="Registry" type="Adf.Config.IpGroupSection,Adf"/> <section name="Authorization" type="System.Configuration.DictionarySectionHandler" /> </configSections> <appSettings> <!-- 服务监控IP,不配置则仅本机可浏览 --> <!--<add key="ServiceMonitorIp" value="*"/>--> <!-- 服务监控端口 --> <add key="ServiceMonitorPort" value="8456"/> <!--日志刷新值--> <add key="Log:FlushInterval" value="10"/> <!-- 日志路径 --> <add key="Log:Path" value="c:\log\adf.service"/> <!-- 禁止安装完成后自动启动 --> <!--<add key="ServiceInstalledStart" value="false"/>--> <!-- 服务使用的帐户,默认: LocalSystem, 还可系统帐户 LocalService,NetworkService 系统帐户时不配置密码, 自建帐户需配置密码 --> <!--<add key="ServiceUsername" value=""/>--> <!--<add key="ServicePassword" value=""/>--> <!-- 本服务依赖的服务清单,多个以半角分号隔开 --> <!--<add key="ServiceDepended" value="server1;server2;server3"/>--> </appSettings> <!-- Cluster Check Interval, seconds,default 10 --> <!--<cluster check="1"> <add ip="127.0.0.1" port="8456" level="1" /> <add ip="127.0.0.2" port="8456" /> <add ip="127.0.0.3" port="8456" /> </cluster>--> <!-- Registry Server List, check is register period, suggest: ip use dns name --> <!--<Registry check="60"> <add ip="127.0.0.1" port="200" /> </Registry>--> <!-- 允许访问的用户名及密码 --> <!--<Authorization> <add key="username1" value="password" /> <add key="username2" value="password" /> </Authorization>--> <startup> <supportedRuntime version="v2.0.50727"/> </startup> </configuration>
调试:
调试配置
1、 右键项目->属性->调试->命令行参数->输入 /c
如图:
配置完成后按 F5 启动应用
监控面板:
此服务自带监控面板
http://ServiceMonitorIp:ServiceMonitorPort /
其它:
服务应用成功后, 在Start 方法中初始化一个Adf.Cs.ServerListen 可以搭建一个Cs项目
CS 应用参考 :http://www.xiaobo.li/adf/513.html
参考:
Adf.Cs.ServerListen listen; public void Start(Adf.Service.ServiceContext serviceContext) { this.listen = new Adf.Cs.ServerListen(serviceContext.Logger); //是否自动注册到注册中心 if (serviceContext.Registry.Enable) { var node = new Dictionary<string, object>(); node.Add("group", serviceContext.Setting.ServiceName); node.Add("port", this.listen.Port); serviceContext.Registry.RegisterNode(node); } } public void Stop(Adf.Service.ServiceContext serviceContext) { this.listen.Dispose(); }
Adf.RegistryServer 是一个常规主机注册服务
下载:
http://www.aooshi.org/adf/download/Adf.RegistryServer.1.0.zip
源代码:
安装:
下载后解压
点击目录下 ToolInstallService.bat 进行安装
非管理员时请点击右链选择”以管理员运行“
配置说明:
<?xml version="1.0"?> <configuration> <configSections> <section name="Authorization" type="System.Configuration.DictionarySectionHandler" /> </configSections> <appSettings> <!-- 服务监听IP,不指定默认本机接口 --> <!--<add key="ServiceMonitorIp" value="127.0.0.1"/>--> <!-- 服务监控端口 --> <add key="ServiceMonitorPort" value="200"/> <!-- 日志存储路径 --> <add key="Log:Path" value="C:\Logs\Adf.RegistryServer"/> <!-- 日志刷新时间间隔(秒) --> <add key="Log:FlushInterval" value="10"/> <!-- 检查周期(秒) --> <add key="InspectInterval" value="5"/> <!-- 检测成功上线阀值 --> <add key="UpThreshold" value="3"/> <!-- 检测失败下线阀值 --> <add key="DownThreshold" value="3"/> </appSettings> <!-- 允许访问的用户名及密码 --> <!--<Authorization> <add key="username1" value="password" /> <add key="username2" value="password" /> </Authorization>--> <startup> <supportedRuntime version="v2.0.50727"/> </startup> </configuration>
参数 ServiceMonitorIp 数默认注释掉,仅本机可加接, 若需其它主机能连接 打开配置并设置值为 *
<add key="ServiceMonitorIp" value="*"/>
授权:
默认配置不开启授权, 需要授权时,配置 Authorization 节点,填写相应的帐户名或密码
监控面板:
http://host:port/
ServiceMonitorPort 端口默认: 200
应用参考:
http://www.xiaobo.li/adf/518.html
.
GNU General Public License (GPL)的可能是开源项目最常用的许可证。GPL赋予和保证了开源项目开发者广泛的权利。基本上,它允许用户合法复制,分发和修改软件。 这意味着你可以:
复制软件到自己的服务器,客户端的服务器,你自己的电脑,几乎任何你想要的地方,而且没有数量限制。
发布你想要的软件,例如,在你的网站提供下载链接,刻成光盘,打印出来等等。
如果你想在向别人提供软件时收费,如设置在别人的网站上或者其他用途时。GPL允许你这么做,但是你必须给客户提供一个GPL副本,告诉 他们可以在其他地方得到免费版本。当然最好在此之前,告诉客户,你为什么收费。
如果你想添加或删除功能,没问题。如果想在其他项目中使用部分代码,也是可以的,但是唯一的限制是此项目也必须按GPL发布。
商业软件不能使用GPL协议的代码。
还
有另一个GNU License:GNU Lesser General Public License
(LGPL)。比起GPL它授予的权限较少。一般来说,LGPL比较适合连接到非GPL或者非开源文件的库文件。由于GPL的规定,使用到部分GPL代码
的软件,必须也使用GPL,开发人员不能使用GPL来开发收费软件或者专有软件。LGPL则没有这方面的要求,不要求使用与部分代码相同的
License。
商业软件可以使用,但不能修改LGPL协议的代码。
BSD
License与其他自由软件License相比,如GPL,限制更少。但是请注意到BSD License两种版本之间的差别:New BSD
License/Modified BSD License 和Simplified BSD License/FreeBSD
License。它们两者都是于GPL兼容的自由软件License。
New
BSD License (”3-clause license”)
可以用于任何作为版权声明和保证许可的免责声明的目的,可以通过无限长的再分发来得以维持,也就是说如果再发布的产品中包含源代码,则在源代码中必须带有
原来代码中的BSD协
议。它还有一个特殊限制条款,不用特别的许可就是限制使用派生工作的工作者名字,也就是说不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。
New BSD License和Simplified BSD License的主要区别是,后者忽略了非认可条款。
商业软件可以使用,也可以修改使用BSD协议的代码。
MIT是和BSD一样宽松的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二 进制发布的还是以源代码发布的。
商业软件可以使用,也可以修改MIT协议的代码,甚至可以出售MIT协议的代码。
Mozilla
Public License 1.1
(MPL)协议允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者。这种授权维护了商业软件的利益,,它要求基于这种软件得修改无偿贡献
版权给该软件。这样,围绕该软件得所有代码得版权都集中在发起开发人得手中。但MPL是允许修改,无偿使用得。MPL软件对链接没有要求。
商业软件可以使用,也可以修改MPL协议的代码,但修改后的代码版权归软件的发起者。
CDDL(Common
Development and Distribution License,通用开发与销售许可)开源协议,是MPL(Mozilla Public
License)的扩展协议,它允许公共版权使用,无专利费,并提供专利保护,可集成于商业软件中,允许自行发布许可。
商业软件可以使用,也可以修改CDDL协议的代码。
Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布 (作为开源或商业软件)。需要满足的条件:
Apache Licence也是对商业应用友好的许可。使用者也可以在需要的时候修改代码来满足需要并作为开源或商业产品发布/销售。
商业软件可以使用,也可以修改使用Apache协议的代码。
Eclipse Public License(EPL)是一个与CPL相类似的许可证,任何扩展自Eclipse源码的代码也必须是开源的。
Creative Commons(CC)的许可证不太开放源代码授权,它们通常用于设计项目。 CC许可证有着宽广的定义,每个定义都会授予一定的权利。它有四个基本部分,可以单独或者组合使用。下面是部分概述:
作者必须是作品的原创者。 除此之外,作品可以修改,分发,复制和以其他方式使用。
工作可以修改,分发等等,但必须在一个许可证下。
可以修改,分发等,但不用于商业目的。 关于什么是“商业”,说法比较含糊(没有提供明确的定义),因此您可能需要在自己的项目中澄清这一点。
这意味着您可以复制和分发许可工作,但你不能以任何方式修改,或在原有的基础开发。
商业软件的使用要遵从CC协议的具体规定,最严格的许可证将是“署名,非商业,不能修改”的授权。这意味着你可以自由 共享的工作,但不能改变它,你必须把它归功于原创者。
Common许可证有一些细节性的规定值得参考:
商业软件可以使用,也可以修改Common协议的代码,但要承担代码产生的侵权责任。
Links:
http://www.gnu.org/licenses/gpl.html
https://www.codeproject.com/info/Licenses.aspx
https://opensource.org/licenses
注:以下内容收集于网络:
主题订阅典型产品架构:
队列模式经典产品架构:
典型场景之抢红包:
架构描述: 利用消息服务的队列模型,作为抽奖和发放红包高并发场景的缓冲。利用海量消息堆积能力和消息必达的特性。解决业务高并发下的超卖,漏单等常见问题
适用场景描述: 海量商品库数据离线计算后,结果数据准确无误的推送业务系统;抽奖出现促销活动场景,海量高并发订单下单支付,如何防止漏单和超卖
架构优势: 实现负责业务系统之间的解耦,并弹性可扩展
典型场景之定时任务
架构描述: QUEUE作为订单到支付之间的核心处理模块,简化秒杀原本系统需要考虑峰值并发的技术架构。消息延时发送和VIP插队机制,能保障特定用户的特定业务规则
适用场景: 团购,秒杀,促销活动等业务
使用方法简介:
下载及源码: http://www.aooshi.org/adf
项目添加引用:
Adf.dll
Adf.Cs.dll
protobuf-net.dll
三个程序集
创建通信接口,示例:
注: 不能含有泛型成员,不能是嵌套类型(类中类)
/// <summary> /// 业务接口 /// </summary> public interface ITest { /// <summary> /// 告知服务器客户端时间 /// </summary> /// <param name="time"></param> /// <returns></returns> bool NotifyTime(DateTime time); /// <summary> /// 返回一个指定SIZE的数组 /// </summary> /// <param name="size"></param> /// <returns></returns> int[] GetArray(int size); /// <summary> /// 获取一个分页数据,并指定pageindex,pagesize参数做为hash键 /// </summary> /// <param name="pageindex"></param> /// <param name="pagesize"></param> /// <param name="totalcount"></param> /// <returns></returns> [ClientHashKey("pageindex", "pagesize")] int[] GetDatas(int pageindex,int pagesize, out int totalcount); }
创建服务端业务,以实例接口,示例:
/// <summary> /// 服务端示例 /// </summary> public class TestServer : Adf.Cs.Example.ITest { //注意: 为了安全,用于CS的方法必需标记Command,不标记的为本地方法。 //不标记的情况下客户端请求将会出现找不到命令的异常 /// <summary> /// 告知我客户端时间 /// </summary> /// <param name="time"></param> /// <returns></returns> public bool NotifyTime(DateTime time) { //收到时间了,返回 true return true; } /// <summary> /// 返回指定大小的一组数据 /// </summary> /// <param name="size"></param> /// <returns></returns> public int[] GetArray(int size) { var rand = new Random(); var result = new int[ size ]; for (int i = 0; i < size; i++) { //随机生成一个数 result[i] = rand.Next(); } return result; } /// <summary> /// 返回一个分页数据 /// </summary> /// <param name="pageindex"></param> /// <param name="pagesize"></param> /// <param name="totalcount"></param> /// <returns></returns> public int[] GetDatas(int pageindex, int pagesize, out int totalcount) { //因为是示例,此处业务不完整, 直接返回指定尺寸数据 totalcount = int.MaxValue; return this.GetArray(pagesize); } }
服务端启动配置,示例
var logManager = new Adf.LogManager("test"); var listen = new Adf.Cs.ServerListen(logManager);
服务端需要的配置,示例
<configSections> <section name="ServerMap" type="System.Configuration.NameValueSectionHandler"/> </configSections> <!-- 服务映射 --> <ServerMap> <!-- 客户端Test映射到 Adf.Cs.ExampleServer 程序集的 Adf.Cs.ExampleServer.TestServer 类 --> <add key="Test" value="Adf.Cs.ExampleServer.TestServer,Adf.Cs.ExampleServer"/> </ServerMap> <appSettings> <!-- 服务端口 --> <add key="Port" value="4562"/> <!-- 日志存储路径 --> <add key="Log:Path" value="D:\logs\Adf.Cs\TestServer"/> <!-- 日志刷新时间间隔(秒) --> <add key="Log:FlushInterval" value="10"/> </appSettings>
创建客户端,示例:
/// <summary> /// 测试客户端 /// </summary> public static class TestClient { //指示服务名为: Test //服务器为配置文件中的: TestServer 节点 /// <summary> /// 通用实例 /// </summary> public static ITest Instance = Adf.Cs.CsHelper.GetClient<ITest>("Test", "TestServer"); }
使用示例:
var notifyResult = TestClient.Instance.NotifyTime(DateTime.Now); Console.WriteLine("告诉服务器客户端时间:" + notifyResult); var array = TestClient.Instance.GetArray(5); Console.WriteLine("从服务器获取到数据:" + Adf.ConvertHelper.ArrayToString(array, ",")); var totalcount = 0; var datas = TestClient.Instance.GetDatas(1, 10, out totalcount); Console.WriteLine("从服务器获取第1页数据:" + totalcount + Adf.ConvertHelper.ArrayToString(datas, ",")); Console.WriteLine("数据在服务器的总量为:"+ totalcount);
客户端需要的配置:
<configSections> <section name="TestServer" type="Adf.Config.IpGroupSection,Adf"/> </configSections> <appSettings> <!-- 日志存储路径 --> <add key="Log:Path" value="C:\Logs\Adf.Cs\TestClient"/> <!-- 日志刷新时间间隔(秒) --> <add key="Log:FlushInterval" value="10"/> </appSettings> <!-- Servers 指定, 当前仅开放一个服务 --> <TestServer hash="0"> <add ip="127.0.0.1" port="4562"/> </TestServer>
示例项目下载:
http://www.aooshi.org/adf/download/Adf.Cs.1.x.Example.zip
备忘:
应用程序提示:
unknown publisher
This file came from another computer and might be blocked to help protect this computer
单个文件: 右键 -> 解锁
多个文件:下载Microsoft提供的如下工具
Streams(http://technet.microsoft.com/en-us/sysinternals/bb897440.aspx)
使用方法:
> streams.exe -s -d directory
如:
>streams.exe -s -d c:\temp
网络字节序: MSB 高字节前存法 Most Significant Bit (Big Edian)
主机字节序: LSB 低字节前存法 Lest Significant Bit (Little Edian)
----------------------------------------------------------------------------------------------
MSB / Big Endian:最高字节在地址最低位,最低字节在地址最高位,依次排列。
LSB / Little Endian:最低字节在最低位,最高字节在最高位,反序排列。
----------------------------------------------------------------------------------------------
当在本地主机上,无需注意机器用的是Big Endian还是Little Endian。
但是网络上都是用的是Big Endian,需要进行一个转换,C#提供的BitConverter默认使用的Little
Endian,在需与网络通信时,反的字节序大有不便,特此提供一个可选Big Endian和Little Endian类方便转换。
为什么存在Little Endian?因为对于机器来说,Little Endian更有利于机器的运算。内存地址由低位到高位,在两个数相加运算,直接在高位添加进位数,不必移动内存地址
x86系列CPU 一般采用little endian方式存储数据
----------------------------------------------------------------------------------------------
Most Significant Bit, Last(Least) Significant Bit
最高有效位(MSB)
指二进制中最高值的比特。在16比特的数字音频中,其第1个比特便对16bit的字的数值有最大的影响。例如,在十进制的15,389这一数字中,相当于万数那1行(1)的数字便对数值的影响最大。比较与之相反的“最低有效位”(LSB)。
MSB高位前导,LSB低位前导。
谈到字节序的问题,必然牵涉到两大CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?
其实big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。
用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:
Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
从上面两图可以看出,采用big endian方式存储数据是符合我们人类的思维习惯的。而little endian,!@#$%^&*,见鬼去吧 -_-|||
为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而J***A编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的J***A程序互通时会产生什么结果?就拿上面的0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了J***A程序,由于J***A采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给J***A程序之前有必要进行字节序的转换工作。
无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。ANSI C中提供了下面四个转换字节序的宏。
·BE和LE一文的补完
我在8月9号的《Big Endian和Little Endian》一文中谈了字节序的问题,原文见上面的超级链接。可是有朋友仍然会问,CPU存储一个字节的数据时其字节内的8个比特之间的顺序是否也有big endian和little endian之分?或者说是否有比特序的不同?
实际上,这个比特序是同样存在的。下面以数字0xB4(10110100)用图加以说明。
Big Endian
msb lsb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Little Endian
lsb msb
---------------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
实际上,由于CPU存储数据操作的最小单位是一个字节,其内部的比特序是什么样对我们的程序来说是一个黑盒子。也就是说,你给我一个指向0xB4这个数的指针,对于big endian方式的CPU来说,它是从左往右依次读取这个数的8个比特;而对于little endian方式的CPU来说,则正好相反,是从右往左依次读取这个数的8个比特。而我们的程序通过这个指针访问后得到的数就是0xB4,字节内部的比特序对于程序来说是不可见的,其实这点对于单机上的字节序来说也是一样的。
那可能有人又会问,如果是网络传输呢?会不会出问题?是不是也要通过什么函数转换一下比特序?嗯,这个问题提得很好。假设little endian方式的CPU要传给big endian方式CPU一个字节的话,其本身在传输之前会在本地就读出这个8比特的数,然后再按照网络字节序的顺序来传输这8个比特,这样的话到了接收端不会出现任何问题。而假如要传输一个32比特的数的话,由于这个数在littel endian方存储时占了4个字节,而网络传输是以字节为单位进行的,little endian方的CPU读出第一个字节后发送,实际上这个字节是原数的LSB,到了接收方反倒成了MSB从而发生混乱。
参考:
https://blog.csdn.net/yusiguyuan/article/details/13023955