应用集成原理与工具参考资料.docx
《应用集成原理与工具参考资料.docx》由会员分享,可在线阅读,更多相关《应用集成原理与工具参考资料.docx(49页珍藏版)》请在冰豆网上搜索。
![应用集成原理与工具参考资料.docx](https://file1.bdocx.com/fileroot1/2023-5/29/8f30425c-fc2a-420a-9826-d567b533e2ff/8f30425c-fc2a-420a-9826-d567b533e2ff1.gif)
应用集成原理与工具参考资料
应用集成原理与工具
参考资料
准备知识:
第1章进程、线程与网络协议
1.1进程和线程
进程是对一段静态指令序列(程序)的动态执行过程,是系统进行资源分配和调度的一个基本单位。
与进程相关的信息包括:
进程的用户标志、正在执行的已经编译好的程序、进程程序和数据在存储器中的位置等。
同一个进程又可以划分为若干个独立的执行流,我们称之为线程。
线程可以看作是进程的一个实例,是CPU调度和分配的基本单位。
在Windows环境下,用户可以同时运行多个应用程序,每个执行的应用程序就是一个进程。
并行性的主要特点:
并发处理
在一个单处理器系统中可以通过分时处理来获得并发,系统为每个线程分配一个CPU时间片,每个线程只有在分配的时间片内才拥有对CPU的控制权,其它时间都在等待。
1.1.1Process类
Process类位于System.Diagnostics名称空间下,它专门用于完成系统进程的管理任务。
可以在本地计算机上启动和停止进程,也可以向进程查询特定类型的信息。
在远程计算机上,无法启动和停止进程,但可以查询进程的相关信息。
在对进程进行操作时,首先要创建Process类的实例,其次还需要设置其对象成员的StartInfo属性,最后调用它的Start方法。
例.启动、停止和观察进程
1.新建一个名为ProcessExample的Windows应用程序。
2.从工具箱中将Process组件拖放到设计窗体。
3.添加名称空间:
usingSystem.Diagnostics;
usingSystem.Threading;
4.添加“启动记事本”、“停止记事本”和“观察所有进程”三个按钮,并添加Click事件代码:
privatevoidbuttonStart_Click(objectsender,EventArgse)
{
process1.StartInfo.FileName="notepad.exe";
//启动Notepad.exe进程.
process1.Start();
}
privatevoidbuttonStop_Click(objectsender,EventArgse)
{
//创建新的Process组件的数组,并将它们与指定的进程名称(Notepad)的所有进程资源相关联.
Process[]myprocesses;
myprocesses=Process.GetProcessesByName("Notepad");
foreach(Processinstanceinmyprocesses)
{
//设置终止当前线程前等待1000毫秒
instance.WaitForExit(1000);
instance.CloseMainWindow();
}
}
privatevoidbuttonView_Click(objectsender,EventArgse)
{
listBox1.Items.Clear();
//创建Process类型的数组,并将它们与系统内所有进程相关联
Process[]processes;
processes=Process.GetProcesses();
foreach(Processpinprocesses)
{
//由于访问Idle的StartTime会出现异常,所以将其排除在外
if(p.ProcessName!
="Idle")
{
//将每个进程名和进程开始时间加入listBox1中
this.listBox1.Items.Add(
string.Format("{0,-30}{1:
h:
m:
s}",p.ProcessName,p.StartTime));
}
}
}
1.1.2Thread类
在System.Threading名称空间下,Thread类是用于创建和控制线程的,对线程的常用操作有:
启动线程、终止线程、合并线程和让线程休眠等。
启动线程
在使用线程前,首先要创建一个线程。
其一般形式为:
Threadt=newThread(enterPoint);
其中enterPoint为线程的入口,即线程开始执行的方法。
在托管代码中,是通过委托处理线程执行的代码的。
例:
Threadt=newThread(newThreadStart(methodName));
创建线程实例后,就可以调用Start方法启动线程了。
终止线程
线程启动后,当不需要某个线程继续执行的时候,就需要终止该线程。
终止线程调用Thread类的Abort方法。
例如:
t.Abort();
Abort方法没有参数。
当调用Abort方法时,公共语言运行库(CLR)可能不会立即终止线程。
主线程调用子线程的Abort方法后,结束子线程会占用大量CPU的时间,表面上看就像死机。
为解决这个问题,可以在主线程中调用子线程对象的Join方法,并在Join方法中指定主线程等待子线程结束的等待时间。
合并线程
Join方法用于把两个并行执行的线程合并为一个单个的线程。
如果一个线程t1在执行的过程中需要等待另一个线程t2结束后才继续执行,可以在t1中调用t2的join()方法。
如:
t2.Join();
这样t1在执行到t2.join()语句后就会处于组塞状态,直到t2结束后才会继续执行。
为了解决假如t2一直不结束的问题,可以在调用t2的Join方法的时候指定一个等待时间。
如:
t2.Join(100);
Join方法通常和Abort一起使用。
让线程休眠
在多线程应用程序中,有时候并不希望某一个线程继续执行,而是希望该线程停止一段时间,等待其它线程执行之后再接着执行。
这时可以调用Thread类的Sleep方法,即让线程休眠。
例如:
Thread.Sleep(1000);
这条语句的功能是让当前线程休眠1000毫秒。
注意,调用Sleep方法的是类本身,而不是类的实例。
休眠的是该语句所在的线程,而不是其他线程。
线程优先级
在C#应用程序中,可以对线程设定五个不同的优先级,由高到低分别是Highest、AboveNormal、Normal、BelowNormal和Lowest。
在创建线程时如果不指定其优先级,
则系统默认为Normal。
若想让一些重要的线程优先执行,可以使用下面的方法为其赋予较高的优先级:
Threadt=newThread(newThreadStart(enterpoint));
t.priority=ThreadPriority.AboveNormal;
设置线程的优先级可改变线程的执行顺序,所设置的优先级仅适用于这些线程所属的进程。
当把某线程的优先级设置为Highest时,系统正在运行的其它线程都会终止。
线程池
线程池是一种多线程处理形式,线程池为线程生命周期的开销问题和资源不足问题提供了很好的解决方案。
通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。
线程池适用于需要多个线程而实际执行时间又不多的场合。
但是如果线程要求运行的时间比较长的话,那么此时线程的运行时间比线程的创建时间要长得多,仅靠减少线程的创建时间对系统效率的提高就不是那么明显了,此时就不适合使用线程池技术
同步
同步指在某一时刻只有一个线程可以访问变量或者对象。
线程t1对variable1操作时,为了避免其他线程也对其进行操作,可以使用C#提供的lock语句将variable1锁定。
实现代码为:
lock(variable1);
{
variable1+=1;
}
注意:
不要将被同步的对象声明为public。
例.在程序中使用线程
1.新建一个名为ThreadExample的Windows应用程序。
2.向设计窗体拖放一个Timer组件。
3.名称空间:
usingSystem.Threading;
4.字段声明:
StringBuildersb=newStringBuilder();
Threadthread1;
Threadthread2;
5.代码:
privatevoidAppendString(strings)
{
lock(sb)
{
str.Append(s);
}
}
publicvoidMethod1()
{
while(true)
{
Thread.Sleep(100);//线程休眠100毫秒
AppendString("a");
}
}
publicvoidMethod2()
{
while(true)
{
Thread.Sleep(100);//线程休眠100毫秒
AppendString("b");
}
}
6.启动线程和终止线程按钮的Click事件中添加代码:
privatevoidbuttonStart_Click(objectsender,EventArgse)
{
sb.Remove(0,sb.Length);
timer1.Enabled=true;
thread1=newThread(newThreadStart(Method1));
thread2=newThread(newThreadStart(Method2));
thread1.Start();
thread2.Start();
}
privatevoidbuttonAbort_Click(objectsender,EventArgse)
{
thread1.Abort();
thread1.Join(10);
thread2.Abort();
thread2.Join(10);
}
7.timer1的Tick事件代码:
privatevoidtimer1_Tick(objectsender,EventArgse)
{
if(thread1.IsAlive==true||thread2.IsAlive==true)
{
richTextBox1.Text=sb.ToString();
}
else
{
timer1.Enabled=false;
}
}
键编译并执行,单击启动线程后,等一会再单击终止线程,查看运行结果。
1.1.3在一个线程中操作另一个线程的控件
默认情况下,为了防止引起死锁等不安全因素,C#不允许在一个线程中直接操作另一个线程中的控件。
但是在Windows应用程序中,为了在窗体上显示线程中处理的信息,我们可能需要经常在一个线程中引用另一个线程中的窗体控件。
比较常用的办法是使用委托(delegate)来完成这个工作。
例.一个线程操作另一个线程的控件的方法。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
usingSystem.Threading;
namespaceThreadControlExample
{
publicpartialclassForm1:
Form
{
Threadthread1;
Threadthread2;
delegatevoidAppendStringDelegate(stringstr);
AppendStringDelegateappendStringDelegate;
publicForm1()
{
InitializeComponent();
appendStringDelegate=newAppendStringDelegate(AppendString);
}
privatevoidAppendString(stringstr)
{
richTextBox1.Text+=str;
}
privatevoidMethod1()
{
while(true)
{
Thread.Sleep(100);//线程1休眠100毫秒
richTextBox1.Invoke(appendStringDelegate,"a");
}
}
privatevoidMethod2()
{
while(true)
{
Thread.Sleep(100);//线程2休眠100毫秒
richTextBox1.Invoke(appendStringDelegate,"b");
}
}
privatevoidbuttonStart_Click(objectsender,EventArgse)
{
richTextBox1.Text="";
thread1=newThread(newThreadStart(Method1));
thread2=newThread(newThreadStart(Method2));
thread1.Start();
thread2.Start();
}
privatevoidbuttonStop_Click(objectsender,EventArgse)
{
thread1.Abort();
thread1.Join();
thread2.Abort();
thread2.Join();
MessageBox.Show("线程1、2终止成功");
}
}
}
1.2IP地址与端口
IP(InternetProtocol)是internet网络设备之间传输数据的一种协议。
本节所讲的端口虽逻辑意义上的端口,是指TCP/IP协议中的端口。
这一节我们将对IPAddress、IPHostEntry、IPEndPoint等System.Net命名空间中的几个类进行简单的介绍。
1.2.1TCP/IP网络协议
网络协议
TCP/IP
IP地址
1.2.2IPAddress类与Dns类
IPAddress类提供了对IP地址的转换、处理等功能。
其Parse方法可将IP地址字符串转换为IPAddress实例。
如:
IPAddressip=IPAddress.Parse(“192.168.1.1”);
IPAddress类提供了7个只读字段:
Any表示本地系统可用的任何IP地址
Broadcast表示本地网络的IP广播地址
IPv6AnySocket.Bind方法用此字段指出本地系统可用的IP地址
IPv6Loopback表示系统的回送地址
IPv6None表示系统上没有可用的网络接口
Loopback表示系统的回送地址
None表示系统上没有可用的网络接口
Dns类提供了一系列静态的方法,用于获取提供本地或远程域名等功能,常用方法有:
1)GetHostAddresses方法
获取指定主机的IP地址,返回一个IPAddress类型的数组。
函数原形为:
publicstaticIPAddress[]GetHostAddresses(stringhostNameOrAddress);
例如:
IPAddress[]ip=Dns.GetHostAddresses("");
listBox1.Items.AddRange(ip);
2)GetHostName方法
获取本机主机名。
例如:
stringhostname=Dns.GetHostName();
1.2.3IPHostEntry类
IPHostEntry类的实例对象中包含了Internet主机的相关信息。
常用属性有:
AddressList属性和HostName属性。
AddressList属性作用:
获取或设置与主机关联的IP地址列表,是一个IPAddress类型的数组,包含了指定主机的所有IP地址;HostName属性则包含了服务器的主机名。
在Dns类中,有一个专门获取IPHostEntry对象的方法,通过IPHostEntry对象,可以获取本地或远程主机的相关IP地址。
例如:
listBox1.Items.Add("搜狐新闻所用的服务器IP地址有:
");
IPAddress[]ip=
Dns.GetHostEntry("").AddressList;
listBox1.Items.AddRange(ip);
listBox1.Items.Add("本机IP地址为:
");
ip=Dns.GetHostEntry(Dns.GetHostName()).AddressList;
listBox1.Items.AddRange(ip);
1.2.4IPEndPoint类
在C#中,IPEndPoint类包含了应用程序连接到主机上的服务所需的IP地址和端口信息。
IPEndPoint类常用的构造函数为:
publicIPEndPoint(IPAddress,int);
其中第一个参数指定IP地址,第二个参数指定端口号。
例:
IPAddress类、Dns类、IPHostEntry类和IPEndPoint类的使用方法。
usingSystem;
usingSystem.Net;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
namespaceIPExample
{
publicpartialclassForm1:
Form
{
publicForm1()
{
InitializeComponent();
}
privatevoidbutton1_Click(objectsender,EventArgse)
{
listBox1.Items.Clear();
stringname=Dns.GetHostName();
listBox1.Items.Add("本机主机名:
"+name);
IPHostEntryme=Dns.GetHostEntry(name);
listBox1.Items.Add("本机所有IP地址:
");
foreach(IPAddressipinme.AddressList)
{
listBox1.Items.Add(ip);
}
IPAddresslocalip=IPAddress.Parse("127.0.0.1");
IPEndPointiep=newIPEndPoint(localip,80);
listBox1.Items.Add("TheIPEndPointis:
"+iep.ToString());
listBox1.Items.Add("TheAddressis:
"+iep.Address);
listBox1.Items.Add("TheAddressFamilyis:
"+iep.AddressFamily);
listBox1.Items.Add("Themaxportnumberis:
"+IPEndPoint.MaxPort);
listBox1.Items.Add("Theminportnumberis:
"+IPEndPoint.MinPort);
}
privatevoidbutton2_Click(objectsender,EventArgse)
{
listBox1.Items.Clear();
IPHostEntryremoteHost=Dns.GetHostEntry("");
IPAddress[]remoteIP=remoteHost.AddressList;
listBox1.Items.Add("中央电视台:
");
foreach(IPAddressipinremoteIP)
{
IPEndPointiep=newIPEndPoint(ip,80);
listBox1.Items.Add(iep);
}
}
}
}
1.3套接字
套接字是支持TCP/IP协议的网络通信的基本操作单元。
可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。
套接字通常和同一个域中的套接字交换数据,各种进程使用
这个相同的域互相之间用Internet协议进行通信。
套接字有两种不同的类型:
流套接字和数据报套接字。
要通过互联网进行通信,至少需要一对套接字,其中一个运行于客户端,称之为ClientSocket,另一个运行于服务器端,称之为ServerSocket。
根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:
服务器监听,客户端请求,连接确认。
服务器监听:
指服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。
客户端请求:
指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。
连接确认:
指当服务器端套接字监听到或接收到客户端套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的信息发给客户端,一旦客户端确认了此信息,连接即可建立。
套接字处理数据两种基本模式:
同步套接字和异步套接字。
同步套接字
其特点是在通过Socket进行连接、接收、发送操作时,客户机或服务器在接收到对方响应前会处于阻塞状态。
它适用于数据处理不太多的场合。
异步套接字
在通过Socket进行连接、接收、发送操作时,客户机或服务器不会处于阻塞方式,而是利用callback机制进行连接、接收和发送处理,这样就可以在调用发送或接收的方法后直接返回,并继续执行下面的程序。
1.3.2面向连接的套接字
IP连接领域有两种通信类型:
面向连接的(connection-oriented)
在面向连接的套接字中,使用TCP协议来建立两个IP地址端点之间的会话。
一旦建立了这种连接,就可以在设备之间可靠的传输数据。
无连接的(connectionless)
为了建立面向连接的套接字,服务器和客户端必须分别进行编程。
对于服务器端程序,建立的套接字必须