Contents
- 网络应用编程入门知识
- 进程、线程与应用程序域
- 数据流与数据的加密解密
- 异步编程
- 并行编程
- WCF入门
- WCF和HTTP应用编程
1章,网络应用编程所需的基本知识
- 包括开发环境、开发模型、网络通信模式、网络协议、IP地址转换、域名解析以及网卡信息检测等
4章,数据流与数据的加密解密
- 介绍数据编码和解码、数据流以及数据的加密和解密技术,这是理解网络数据传输以及网络数据安全性控制等高级应用的基础
3、5、6章,多进程 多线程 异步 并行编程技术
- 介绍进程管理、多线程编程以及应用程序域的基本用法,如何用多任务实现异步和并行编程。在多核处理器、云计算和大数据处理流行的今天,异步和并行编程是高级网络应用的基础,也是必须掌握的基本技能
7~11章,WCF网络编程框架
- 介绍面向服务的WCF编程入门知识和基本用法。如何用WCF和WPF编写基于HTTP、TCP、UDP以及MSMQ的网络应用程序,这是实际项目中使用最多的协议类网络编程技术
网络应用编程入门知识
- 安装VisualStudio开发环境
- 网络应用编程模型
- TCP/IP网络协议
- IP地址转换与域名解析
- 网卡信息检测与网络流量检测
流行模式:
- C/S,Client / Server,客户端 / 服务器;
P2P,客户端和服务器都有,效率更高一些;
B/S,Browser / Server,浏览器 / 服务器;
以 WPF 和 WCF 为主要基础,知识架构:
网络的两个含义:
- 互联网 (Internet);互联网是一个大筐,装着万维网,万维网是个小筐,装了无数超链接.
- 企业内部网 (Intranet),将企业内部网和外部网络通过防火墙有效隔离;
数据通信模型:
- 分散式 (Decentralized) ,各管各的,早已被淘汰;
- 集中式 (Centralized),终端不能处理信息,所有数据、运作、管理全都交给主机;
- 分布式 (Distributed),分散式+集中式,资源以透明方式供用户使用
分布式系统与计算机网络的主要区别是软件而非硬件;
现在企业管理系统一般是分布式 + 集中式的综合;
C/S 模式,又叫 C/S 架构或 C/S 模型
- 以分布式为基础,抽象出来的编程模型
主要工作在客户端;
将一个网络事务处理分为两部分,客户端、服务端;
面向服务的体系架构 (SOA),WCF 是其中一种具体实现技术;
用 WCF 编写服务端应用程序;
用 WPF 编写客户端应用程序;
B/S模式,仅使用 HTTP 进行通信;(我们主要学 C/S 模式)
采用三层架构设计,用户界面(浏览器)、逻辑处理(Web服务器) 和数据支持(数据库服务器);
B/S 模式的应用程序也称为 Web 应用程序;其客户端程序就是浏览器
优点,单台计算机可以访问任何 web 服务器; (只需知道服务器的网址(IP 地址或域名));20.2.19
网络协议 (network protocol),简称协议,为数据交换建立的规则
- HTTP,Hypertext Transfer Protocol 超文本传输协议,是TCP协议族的一员;在应用层;
- 传输层有 TCP、UDP
TCP,传输控制协议;UDP,用户数据报协议;
TCP,使用面向连接的套接字;在正式通信前必须要与对方建立起连接;
UDP,使用无连接的;不提供可靠性保证,用数据包;
链接:TCP、UDP和HTTP区别详解.
计算机网络体系结构 (architecture),OSI 的七层协议、TCP/IP 的四层、还有个五层协议;
为什么要分层?分层细化是一种化繁为简的通用方法;
- TCP/IP 的四层:
应用层,负责应用程序之间的沟通,SMTP、FTP、Telnet;
传输层,负责节点间数据传送,及应用程序间通信服务,TCP、UDP;端口号是其服务接入点;
网际层,负责给数据报最佳路径,核心协议 IP,其他 ICMP、ARP;
网络接口层,负责接收数据报并进行传输;数据报,简单理解为“生成报告后的数据”;
- 套接字,socket
链接:第14章的网络编程. 20.2.25
- 一个 IP 地址由两部分组成,网络号 + 主机号;
IPv4 编址方案,4个字节,点分十进制;
IPv6 编址方案,16个字节,冒号分隔;
- 子网掩码,用于屏蔽 IP 地址的一部分,以区别网络标识和主机标识;
把所有的网络位用1来标识,主机位用0来标识;例如:255.255.255.0 前三个字节就对应网络号;
- 端口,物理意义上的端口是实际的接口;逻辑意义上的端口是进程标识;
- IP 地址转换相关类,命名空间 System.Net;
①IPAddress 类,提供网络协议 IP 地址;
Parse 方法,将 IP 地址字符串转换为其实例;(静态工厂方法)
AddressFamily 属性,判断是 IPv4 还是 IPv6;
②IPEndPoint 类,包含 IP 地址和端口号;
public IPEndPoint(IPAddress address, int port);
③IPHostEntry 类,为主机提供信息容器;
Dns.GetHostEntry()
获得其对象;其实例包含主机相关信息;
AddressList 属性,IP 地址列表;
HostName 属性,包含指定主机名;
- IP 地址不易记,通过 字符型地址(域名,Domain Name) 记;
DNS (Domain Name System 域名系统),可将域名和IP地址相互转换;
Dns 类提供了方便的域名解析功能,即很多静态方法:
GetHostAddresses(String);
GetHostEntry(String);
GetHostName();
- MAC 地址,物理地址;
- 网络适配器,又称网卡 (NIC),是连接计算机与网络的硬件设备;
NetworkInterface 类,检测网卡的配置和统计信息,GetAllNetworkInterfaces();
;
IPInterfaceProperties 类,检测网卡支持的各种地址;抽象类;networkInterface.GetIPProperites();
- 网络流量检测相关类:IPGlobalProperties 类;
- 链接:第一章_代码实现. 20.2.26
进程、线程与应用程序域
- 进程,操作系统级别的概念,正在运行的程序;
既包含被执行的程序所需要的资源,同时还对这些资源进行基本的内存边界管理
是资源调度和分配的基本单位,Process 类;命名空间 System.Diagnostics
- 线程,进程划分后的独立的单条执行流,小进程;
是CPU调度和分配的基本单位,Thread 类;
- 并发,宏观并行,微观串行;
并行,同时执行;
异步,各个线程之间执行时各自运行,无前后关系,无相互等待,执行先后不可知;
- 逻辑内核,一个物理内核 = 两个逻辑内核,普通计算机是一对一;
指一个CPU双核心,就是单核多线程,多核处理器
多线程技术真正实现了多个线程并行执行,而不是通过时间片来实现 宏观并行
System.Environment类 提供的静态ProcessorCount属性
- 启动进程,
1.用类的静态方法 Start()
2.创建类的实例,设置属性 StartInfo 的 FileName 和 Arguments,然后调用实例方法 Start()
关闭进程,
CloseMainWindow(),请求关闭进程;
Kill(),杀死进程,直接杀死,强制关闭;
注:调用方法关闭时若进程已经关闭,会引发异常
可用HasExited属性判断进程是否已关闭
获取进程,
Process 类的静态工厂方法,传参获取远程机所有进程,不传参获取本机;
获取指定进程信息,用 Process 的静态方法 GetProcessById();20.3.11
- 主线程
系统为进程创建的一个默认线程,用于执行 main方法中的代码
main方法返回,主线程终止
在一个进程中,除了主线程都是辅助线程
- 后台线程不会影响进程的终止,前台线程会
若前台线程结束,进程终止,后台线程被迫结束
默认,托管线程池中都是后台线程
- 创建和启动线程
默认前台线程,可用 IsBackground属性设置或判断
调用 Start() 实例方法只是告诉系统启动线程,系统不一定立即启动该线程
Thread t = new Thread(<方法名>);
不带参数方法使用ThreadStart委托
带参数方法使用ParameterizedThreadStart委托
t.Start();
t.Start("abc");
要传多个参数,用自定义类封装一下
对应方法定义参数类型为 Object类型
- 线程的终止和取消
正常终止,volatile 修饰的 bool 型的字段,设为 true
强制终止, Abort() 实例方法,也称线程取消
线程休眠
Sleep() 静态方法,可使当前线程暂停一段时间
无法从一个线程中暂停其他的线程
- 获取或设置线程的优先级
priority 属性,ThreadPriority.AboveNormal,较高优先级
- 线程池 ThreadPool 类
其中线程完成任务时,返回等待队列中,不销毁
只有一些静态方法
用ThreadPool.QueueUserWorkItem方法向线程池中添加工作项
ThreadPool.QueueUserWorkItem(new WaitCallback(Method1));
- 同步执行,一条执行完后另一条执行
异步执行,继续执行不管是否完成
- 资源同步,启动多个线程会并发执行,死锁和争用 lock
数据流与数据的加密解密
- 常用字符集 ASCII,128个字符
Unicode,国际通用,每个字符两个字节
UTF-8,网络常用,Unicode 的变长编码
GB2312 和 GB18030,简体中文
- Encoding 类,命名空间 System.Text
实例方法 GetBytes 编码,GetString 解码
静态方法 GetEncodings 返回 EncodingInfo[]
,
EncodingInfo 的属性获取编码名称,Encoding 的属性获取描述信息
属性中没有 GB2312 和 GB18030 以及 Unicode,需要用GetEncoding("GB2312")
方式获取
静态方法 Convert ,将字符数组的编码转换成另一种编码
String s = "abc";
Encoding unicode = Encoding.GetEncoding("Unicode");
Encoding utf8 = Encoding.UTF8;
byte[] b = Encoding.Convert(unicode, utf8, unicode.GetBytes(s));
string s1 = utf8.GetString(b);
异步编程
任务 Task 表示一个异步操作
Task 类,Task
类
任务延迟 Task.Delay,注意和 Thread.Sleep 区别
async Task 共同签名的方法 叫异步方法
await 运算符 在异步方法内部,等待异步执行的结果,
异步执行完之前 await 后面语句不执行(和同步差不多 不过不影响主界面)
一般异步方法名以 Async 为后缀,例 MethodAsync()
1.普通方法
public void Method1() {…}
2.lambda 匿名
private async void btnStart_Click(…){
await Task.Run(() => {Console.WriteLine("a"); }); }
3.异步方法
public async Task Method1Async() {…}
直接调用 Method1Async(); 不开启新线程
1.Task.Run() 隐式创建和执行
private async void btnStart_Click(…) {
await Task.Run(() => Method1()); }
2.async 隐式创建和执行
仅包含async和await关键字的异步方法不会创建新线程,它只是表示在当前线程中异步执行指定的任务
3.WPF中通过 Dispatcher.InvokeAsync 隐式创建和执行 各线程协调
this.Dispatcher.InvokeAsync(() => Method1Async());
4.显式 Task 和 Task<T> 创建新线程
Task t = new Task(Method1);
t.start();
CancellationTokenSource类 (创建取消源)
CancellationToken结构 (创建取消令牌) 命名空间 System.Threading
二者用于协同实现多个线程、线程池工作项或Task对象的取消操作
发出取消通知
- CancellationToken 对象的 IsCancellationRequested 属性 设为 true
接到通知,两种终止方式
- 正常完成 RanToCompletion
- 引发 OperationCanceledException 异常,并将其传递到在其上请求了取消的标记
调用 CancellationToken 对象的 ThrowIfCancellationRequested 方法
冷任务 cold Task 用构造函数显示创建的任务
热状态 任务在生命周期内的执行状态
任务的执行状态用 TaskStatus 枚举表示,
- 枚举值:
Created:该任务已初始化,但尚未进入调度计划
Running:正在运行
RanToCompletion:已完成
Faulted:因出现未经处理的异常而完成
Canceled:该任务由于被取消而完成(任务自身引发OperationCanceledException异常,
或者在该任务执行之前调用方已向该任务的CancellationToken发出了信号)
并行编程
并行编程的实现
- 业务角度,数据、任务
- 硬件实现,单机多核、多机多核(云计算里讲)
任务并行库 TPL
核心 Parallel 类和 PLINQ
TPL分类
- 数据并行 分数据 For方法 Foreach方法
- 任务并行 Invoke方法
- 并行查询 用PLINQ(不讲)
并行循环的内部不宜频繁与界面交互
Parallel 类的并行方法
Parallel.For(<开始索引>, <结束索引>, <每次迭代执行的委托>)
- Parallel.Foreach 方法
- Parallel.Invoke 方法
Parallel 帮助器类
ParallelOptions option = new ParallelOptions();
option.MaxDegreeOfParallelism = 4 * Environment.ProcessorCount;
- ParallelLoopState 类 并行循环状态
var cb = new ConcurrentBag<Data>();
Action<int, ParallelLoopState> action = (i, loopState) =>
{
Data data = new Data() { Name = "A" + i.ToString(), Number = i };
cb.Add(data);
AddInfo("{0}\t", i);
if (i == 10) loopState.Break();
};
线程全局变量同步和冲突解决方法
Interlocked.Add 原子操作解决资源争用问题
并发集合类ConcurrentBag< T>
自动解决可能会导致冲突的各种问题
Parallel.For 方法
- 简单的Parallel.For循环
For(Int32, Int32, Action)
- 带并行选项的Parallel.For循环
For(Int32, Int32, ParallelOptions, Action)
public static ParallelLoopResult For(
int fromInclusive,
int toExclusive,
ParallelOptions parallelOptions,
Action<int> body
)
- 带并行循环状态的Parallel.For循环
For(Int32, Int32, Action)
public static ParallelLoopResult For(
int fromInclusive,
int toExclusive,
Action<int, ParallelLoopState> body
)
- 带线程局部变量的Parallel.For循环
线程局部变量是指某个线程内的局部变量,其他线程无法访问。
线程局部变量保存的数据称为线程本地数据
public static ParallelLoopResult For<TLocal>(
int fromInclusive,
int toExclusive,
Func<TLocal> localInit,
Func<int, ParallelLoopState, TLocal, TLocal> body,
Action<TLocal> localFinally
)
WCF入门
预备知识
- XML
- Web Service (Web服务)
数据交换格式 XML JSON
Web服务的体系结构基于服务提供者、服务请求者、服务注册中心三个角色,
利用发布、发现、绑定三个操作来构建的
涉及SOAP、WSDL
- RPC(Remote Procedure Call)——远程过程调用
- MQ(Message Queue)是在多个不同的应用程序之间实现相互通信的一种基于队列和事务处理的异步传输模式
- SOA(Service-Oriented Architecture,面向服务的体系结构)
对于.NET开发人员来说,这个基于SOA的具体实现就是WCF
WCF基础知识
- WCF是微软公司推出的符合SOA思想的分布式应用程序技术框架和编程模型
- WCF编程模型的目标是实现以下两个实体之间的通信:WCF服务和WCF客户端
该编程模型封装在.NET框架的 System.ServiceModel 命名空间中
- 终结点(EndPoint)用于确定网络通信目标,
用EndPoint类来实现,在配置文件中用配置节来指定
终结点 由 地址、协定、绑定组成
实例:
<endpoint
address="http://localhost:2338/Service1.svc"
binding="basicHttpBinding"
contract="WcfService.IService1" />
- 地址(Address)用于确定终结点的位置
地址可以是URL、FTP、网络路径或本地路径
格式
[传输协议]://[位置][:端口][/服务路径]
- 绑定(Binding)
WCF通过绑定来定义WCF客户端与WCF服务通信的方式
不论是服务端还是客户端,一般都是在单独的配置文件(Web.config、App.config)中配置绑定
- 协定(Contract)
协定表示客户端和服务端之间的信息交换规则
如果不指定协定,就无法在客户端和服务端之间进行通信
协定在接口中用 Contract 特性来声明,内部用 ContractAttribute 类来实现,在配置文件中用 contract 指定
- 服务端和客户端
准确来说,是进程(或线程)执行的方法、通信对应的IP地址、端口以及相关的协定共同构成终结点
- WCF体系结构
1.协定层
2.服务运行时层
3.消息传递层
4.激活和承载层
- WCF承载
WCF本身不能运行,只能将其“宿主”在某个可执行程序中(.dll或者.exe)才能运行。
承载WCF的方式有三种:
1.利用IIS或者WAS承载WCF服务,最常用的承载方式
WAS(Windows Process Activation Service,Windows进程激活服务)
选 WCF服务应用程序 这种模板
2.利用Windows服务承载WCF服务,利用Windows服务进程激活的方式
选WCF服务库 这种模板
3.自承载方式,比较灵活
WCF服务端和客户端编程基础
编写WCF服务端程序有4个主要步骤:
选择承载方式、设计和实现协定、配置服务、承载服务
-
选择承载方式
编写HTTP应用程序时,一般选择【WCF服务应用程序】模板
编写TCP应用程序时,既可以选择自承载方式,也可以选择【WCF服务应用程序】模板
编写UDP应用程序时,既可以用自承载方式,也可以用标准绑定
-
设计和实现协定的方式
方式1:用一个接口公开多个方法,再用一个类实现接口中声明的所有方法。(建议)
-
配置服务
方式1:通过修改配置文件(Web.config或者App.config)(建议的方式)
优点:部署服务端应用程序时,不需要修改源程序,只需要修改配置文件即可。
方式2:开发人员自己编写代码
-
承载服务
服务端设计完成后,运行(承载)服务即可,此时客户端就可以和服务端交互
-
编写WCF客户端应用程序时,一般用WPF应用程序
-
编写WCF客户端程序的主要步骤如下:
1、利用服务端配置生成客户端代理类和客户端配置
2、编写客户端代码
客户端添加服务引用后,即可利用自动生成的客户端代理类,编写代码与WCF交互。
3、更新客户端配置
-
编写WCF程序的基本步骤如下:
创建服务端项目和客户端项目
编写服务端代码
修改服务端配置
测试服务(可选)
在客户端添加服务引用
编写客户端调用代码
更新服务引用(可选)
WCF和HTTP应用编程
- HTTP,超文本传输协议,应用层协议,TCP/IP顶层
用于客户端与服务器端传输超文本文件
HTTP通讯模式 请求 与 响应
- GET请求(默认) 与 POST请求,还有HEAD请求
string uri = "http://www.google.cn";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
request.Method = "POST";
- GET,后一般跟一个网页的信息
- POST,要求服务器接收大量的信息
- HEAD,用来C-S交流,一般不单独用,辅助作用
HTTP响应,和请求不一样的就是开始的 < status-line > 状态行(请求的开始是请求行 request-line)
- HTTP版本号 + 3位状态码 + 描述状态的短语
HTTP特点
- 以TCP方式工作,建立TCP连接
客户端通过套接字发送HTTP请求,接收HTTP响应
- HTTP是无状态的,服务器不存储客户端的状态信息,只要有请求就发对象
- 使用元信息作为标头 (Header),提供HTTP请求的相关信息
HTTP绑定
- WSHttpBinding 非双工
- WSDualHttpBinding 双工 服务器也可以主动调用客户端方法
客户端和服务端的信息交换模式
- 请求应答模式、单向模式、双工通信,同步异步操作
- Action/Reply,一直等服务器运行,死等
- 单向模式,速度快,客户端不等,服务端不返回操作结果 (即使执行错误)
- 双工通信,服务端也可以主动呼叫客户端
请求应答模式例子步骤
- 1.创建解决方案
2.定义数据协定
3.定义服务协定
4.配置服务
5.客户端添加引用
6.编写客户端代码
单向模式例子步骤
- 1.定义服务协定 IsOneWay = true (不需要返回值的)
2.编写客户端代码
双工通信设计思想及实现步骤
- 1.修改服务端配置,选择合适的绑定方式
- 2.在服务端声明和实现接口,
一个接口用于服务:服务接口
一个接口用于回调:回调接口 (服务端调用,客户端实现)
两个接口中的方法不一定有关联
[ServiceContract(SessionMode=SessionMode.Required,
CallbackContract=typeof(IService1DuplexCallback))]
- 3.在客户端实现回调接口
需要创建 InstanceContext 类的一个实例,以便让服务端知道通信的客户端是哪一个客户端对象
InstanceContext site = new InstanceContext(this);
Service1DuplexClient client = new Service1DuplexClient(site);