《网络应用高级编程第1章进程、线程与网络协议.ppt》由会员分享,可在线阅读,更多相关《网络应用高级编程第1章进程、线程与网络协议.ppt(39页珍藏版)》请在三一办公上搜索。
1、C#编程三剑客,C#网络应用编程基础马骏主编 基础知识部分,适用于初学者。C#网络应用高级编程马骏、郑逢斌、沈夏炯编著 高级编程部分,适用于高级开发者。C#网络应用编程开发实例与实验指导马骏编著 上机题与项目开发实例(从设计到安装程序制作一网打尽)。,C#网络应用高级编程,第1章 进程、线程与网络协议,1.1 进程和线程 1.2 IP地址与端口 1.3 套接字 1.4 网络流,1.1 进程和线程,进程是对一段静态指令序列(程序)的动态执行过程,是系统进行资源分配和调度的一个基本单位。与进程相关的信息包括:进程的用户标志、正在执行的已经编译好的程序、进程程序和数据在存储器中的位置等。同一个进程又
2、可以划分为若干个独立的执行流,我们称之为线程。线程可以看作是进程的一个实例,是CPU调度和分配的基本单位。在Windows环境下,用户可以同时运行多个应用程序,每个执行的应用程序就是一个进程。,1.1 进程和线程(续),并行性的主要特点:并发处理在一个单处理器系统中可以通过分时处理来获得并发,系统为每个线程分配一个CPU时间片,每个线程只有在分配的时间片内才拥有对CPU的控制权,其它时间都在等待。,1.1.1 Process类,Process类位于System.Diagnostics名称空间下,它专门用于完成系统进程的管理任务。可以在本地计算机上启动和停止进程,也可以向进程查询特定类型的信息。
3、在远程计算机上,无法启动和停止进程,但可以查询进程的相关信息。在对进程进行操作时,首先要创建Process类的实例,其次还需要设置其对象成员的StartInfo属性,最后调用它的Start方法。,例.启动、停止和观察进程,1.新建一个名为ProcessExample的Windows应用程序。2.从工具箱中将Process组件拖放到设计窗体。3.添加名称空间:using System.Diagnostics;using System.Threading;4.添加“启动记事本”、“停止记事本”和“观察所有进程”三个按钮,并添加Click事件代码:private void buttonStart_C
4、lick(object sender,EventArgs e)process1.StartInfo.FileName=notepad.exe;/启动Notepad.exe进程.process1.Start();,private void buttonStop_Click(object sender,EventArgs e)/创建新的Process组件的数组,并将它们与指定的进程名称(Notepad)的所有进程资源相关联.Process myprocesses;myprocesses=Process.GetProcessesByName(Notepad);foreach(Process inst
5、ance in myprocesses)/设置终止当前线程前等待1000毫秒 instance.WaitForExit(1000);instance.CloseMainWindow();private void buttonView_Click(object sender,EventArgs e)listBox1.Items.Clear();/创建Process类型的数组,并将它们与系统内所有进程相关联,Process processes;processes=Process.GetProcesses();foreach(Process p in processes)/由于访问Idle的Star
6、tTime会出现异常,所以将其排除在外 if(p.ProcessName!=Idle)/将每个进程名和进程开始时间加入listBox1中 this.listBox1.Items.Add(string.Format(0,-301:h:m:s,p.ProcessName,p.StartTime);,1.1.2 Thread类,在System.Threading名称空间下,Thread类是用于创建和控制线程的,对线程的常用操作有:启动线程、终止线程、合并线程和让线程休眠等。,启动线程 在使用线程前,首先要创建一个线程。其一般形式为:Thread t=new Thread(enterPoint);其中
7、enterPoint为线程的入口,即线程开始执行的方法。在托管代码中,是通过委托处理线程执行的代码的。例:Thread t=new Thread(new ThreadStart(methodName);创建线程实例后,就可以调用Start方法启动线程了。,1.1.2 Thread类(续),终止线程 线程启动后,当不需要某个线程继续执行的时候,就需要终止该线程。终止线程调用Thread类的Abort方法。例如:t.Abort();Abort方法没有参数。当调用Abort方法时,CLR可能不会立即终止线程。主线程调用子线程的Abort方法后,结束子线程会占用大量CPU的时间,表面上看就像死机。为解
8、决这个问题,可以在主线程中调用子线程对象的Join方法,并在Join方法中指定主线程等待子线程结束的等待时间。,1.1.2 Thread类(续),合并线程 Join方法用于把两个并行执行的线程合并为一个单个的线程。如果一个线程t1在执行的过程中需要等待另一个线程t2结束后才继续执行,可以在t1中调用t2的join()方法。如:t2.Join();这样t1在执行到t2.join()语句后就会处于组塞状态,直到t2结束后才会继续执行。为了解决假如t2一直不结束的问题,可以在调用t2的Join方法的时候指定一个等待时间。如:t2.Join(100);Join方法通常和Abort一起使用。,1.1.2
9、 Thread类(续),让线程休眠 在多线程应用程序中,有时候并不希望某一个线程继续执行,而是希望该线程停止一段时间,等待其它线程执行之后再接着执行。这时可以调用Thread类的Sleep方法,即让线程休眠。例如:Thread.Sleep(1000);这条语句的功能是让当前线程休眠1000毫秒。注意,调用Sleep方法的是类本身,而不是类的实例。休眠的是该语句所在的线程,而不是其他线程。,1.1.2 Thread类(续),线程优先级 在C#应用程序中,可以对线程设定五个不同的优先级,由高到低分别是Highest、AboveNormal、Normal、BelowNormal和Lowest。在创建
10、线程时如果不指定其优先级,则系统默认为Normal。若想让一些重要的线程优先执行,可以使用下面的方法为其赋予较高的优先级:Thread t=new Thread(new ThreadStart(enterpoint);t.priority=ThreadPriority.AboveNormal;设置线程的优先级可改变线程的执行顺序,所设置的优先级仅适用于这些线程所属的进程。当把某线程的优先级设置为Highest时,系统正在运行的其它线程都会止。,1.1.2 Thread类(续),线程池 线程池是一种多线程处理形式,线程池为线程生命周期的开销问题和资源不足问题提供了很好的解决方案。通过对多个任务重
11、用线程,线程创建的开销被分摊到了多个任务上。线程池适用于需要多个线程而实际执行时间又不多的场合。但是如果线程要求运行的时间比较长的话,那么此时线程的运行时间比线程的创建时间要长得多,仅靠减少线程的创建时间对系统效率的提高就不是那么明显了,此时就不适合使用线程池技术,1.1.2 Thread类(续),同步 同步指在某一时刻只有一个线程可以访问变量或者对象。线程t1对variable1操作时,为了避免其他线程也对其进行操作,可以使用C#提供的lock语句将variable1锁定。实现代码为:lock(variable1);variable1+=1;注意:不要将被同步的对象声明为public。,例.
12、在程序中使用线程,1.新建一个名为ThreadExample的Windows应用程序。2.向设计窗体拖放一个Timer组件。3.名称空间:using System.Threading;4.字段声明:StringBuilder sb=new StringBuilder();Thread thread1;Thread thread2;5.代码:private void AppendString(string s)lock(sb),str.Append(s);public void Method1()while(true)Thread.Sleep(100);/线程休眠100毫秒 AppendStri
13、ng(a);public void Method2()while(true),Thread.Sleep(100);/线程休眠100毫秒 AppendString(b);6.启动线程和终止线程按钮的Click事件中添加代码:private void buttonStart_Click(object sender,EventArgs e)sb.Remove(0,sb.Length);timer1.Enabled=true;thread1=new Thread(new ThreadStart(Method1);thread2=new Thread(new ThreadStart(Method2);t
14、hread1.Start();,thread2.Start();private void buttonAbort_Click(object sender,EventArgs e)thread1.Abort();thread1.Join(10);thread2.Abort();thread2.Join(10);7.timer1的Tick事件代码:private void timer1_Tick(object sender,EventArgs e)if(thread1.IsAlive=true|thread2.IsAlive=true),richTextBox1.Text=sb.ToString(
15、);else timer1.Enabled=false;键编译并执行,单击启动线程后,等一会再单击终止线程,查看运行结果。,1.1.3 在一个线程中操作另一个线程的控件,默认情况下,为了防止引起死锁等不安全因素,C#不允许在一个线程中直接操作另一个线程中的控件。但是在Windows应用程序中,为了在窗体上显示线程中处理的信息,我们可能需要经常在一个线程中引用另一个线程中的窗体控件。比较常用的办法是使用委托(delegate)来完成这个工作。例.一个线程操作另一个线程的控件的方法。,1.2 IP地址与端口,IP(Internet Protocol)是internet网络设备之间传输数据的一种协议
16、。本节所讲的端口虽逻辑意义上的端口,是指TCP/IP协议中的端口。这一节我们将对IPAddress、IPHostEntry、IPEndPoint等System.Net命名空间中的几个类进行简单的介绍。,1.2.1 TCP/IP网络协议,网络协议TCP/IPIP地址,1.2.2 IPAddress类与Dns类,IPAddress类提供了对IP地址的转换、处理等功能。其Parse方法可将IP地址字符串转换为IPAddress实例。如:IPAddress ip=IPAddress.Parse(“192.168.1.1”);IPAddress类提供了7个只读字段:Any 表示本地系统可用的任何IP地址
17、Broadcast 表示本地网络的IP广播地址IPv6Any Socket.Bind方法用此字段指出本地系统可用的IP地址IPv6Loopback 表示系统的回送地址IPv6None 表示系统上没有可用的网络接口Loopback 表示系统的回送地址None 表示系统上没有可用的网络接口,1.2.2 IPAddress类与Dns类(续),Dns类提供了一系列静态的方法,用于获取提供本地或远程域名等功能,常用方法有:1)GetHostAddresses方法 获取指定主机的IP地址,返回一个IPAddress类型的数组。函数原形为:public static IPAddress GetHostAdd
18、resses(string hostNameOrAddress);例如:IPAddress ip=);listBox1.Items.AddRange(ip);,2)GetHostName方法 获取本机主机名。例如:string hostname=Dns.GetHostName();,1.2.3 IPHostEntry类,IPHostEntry类的实例对象中包含了Internet主机的相关信息。常用属性有:AddressList属性和HostName属性。AddressList属性作用:获取或设置与主机关联的IP地址列表,是一个IPAddress类型的数组,包含了指定主机的所有IP地址;Host
19、Name属性则包含了服务器的主机名。在Dns类中,有一个专门获取IPHostEntry对象的方法,通过IPHostEntry对象,可以获取本地或远程主机的相关IP地址。例如:,1.2.3 IPHostEntry类(续),listBox1.Items.Add(搜狐新闻所用的服务器IP地址有:);IPAddress ip=Dns.GetHostEntry().AddressList;listBox1.Items.AddRange(ip);listBox1.Items.Add(本机IP地址为:);ip=Dns.GetHostEntry(Dns.GetHostName().AddressList;li
20、stBox1.Items.AddRange(ip);,1.2.4 IPEndPoint类,在C#中,IPEndPoint类包含了应用程序连接到主机上的服务所需的IP地址和端口信息。IPEndPoint类常用的构造函数为:public IPEndPoint(IPAddress,int);其中第一个参数指定IP地址,第二个参数指定端口号。例:IPAddress类、Dns类、IPHostEntry类和IPEndPoint类的使用方法。,1.3 套接字,套接字是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。套
21、接字通常和同一个域中的套接字交换数据,各种进程使用 这个相同的域互相之间用Internet协议进行通信。套接字有两种不同的类型:流套接字和数据报套接字。要通过互联网进行通信,至少需要一对套接字,其中一个运行于客户端,称之为ClientSocket,另一个运行于服务器端,称之为ServerSocket。,1.3 套接字(续),根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。服务器监听:指服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。客户端请求:指由客户端的套接字提出连接请求,要连接的目标是
22、服务器端的套接字。连接确认:指当服务器端套接字监听到或接收到客户端套接字的连接请求时,它就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的信息发给客户端,一旦客户端确认了此信息,连接即可建立。,1.3 套接字(续),套接字处理数据两种基本模式:同步套接字和异步套接字。同步套接字 其特点是在通过Socket进行连接、接收、发送操作时,客户机或服务器在接收到对方响应前会处于阻塞状态。它适用于数据处理不太多的场合。异步套接字 在通过Socket进行连接、接收、发送操作时,客户机或服务器不会处于阻塞方式,而是利用callback机制进行连接、接收和发送处理,这样就可以在调用发送或接收的方法
23、后直接返回,并继续执行下面的程序。,1.3.2 面向连接的套接字,IP连接领域有两种通信类型:面向连接的(connection-oriented)在面向连接的套接字中,使用TCP协议来建立两个IP地址端点之间的会话。一旦建立了这种连接,就可以在设备之间可靠的传输数据。无连接的(connectionless)为了建立面向连接的套接字,服务器和客户端必须分别进行编程。对于服务器端程序,建立的套接字必须绑定到用于TCP通信的本地IP地址和端口上。,1.3.2 面向连接的套接字(续),Bind方法用于完成绑定工作:Bind(IPEndPoint address)Address为IPEndPoint的实
24、例,该实例包括一个本地IP地址和一个端口号。在套接字绑定到本地之后,就用Listen方法等待客户机发出的连接尝试:Listen(int backlog)Backlog参数指出系统等待用户程序服务排队的连接数,超过连接数的任何客户都不能与服务器进行通信。在Listen方法执行之后,服务器已经做好了接收任何引进连接的准备,这是用Accept方法来完成的,当有新客户进行连接时,该方法就返回一个新的套接字描述符。,1.3.3 无连接的套接字,UDP协议使用无连接的套接字,不需要在网络设备之间发送连接信息。UDP客户机不需要Connect方法。由于不存在确定的连接,所以可以直接使用SendTo方法和Re
25、ceiveFrom方法发送和接收数据,在两个设备之间的通信结束之后,可以像TCP中使用的方法一样,对套接字使用Shutdown和Close方法。需要接收数据时,必须使用Bind方法将套接字绑定到一个本地地址/端口对上后才能使用ReceiveFrom方法接收数据,如果只发送而不接收,则不需要使用Bind方法。,1.4 网络流,流(stream)是对串行传输的数据的一种抽象表示,底层的设备可以是文件、外部设备、主存、网络套接字等。流有三种基本的操作:写入、读取和查找。若数据从内存缓冲区传输到外部源,这样的流叫作“写入流”。若数据从外部源传输到内存缓冲区,这样的流叫作“读取流”。C#在名称空间中提供
26、了一个专门的NetworkStream类,用于通过网络套接字发送和接收数据。NetworkStream类支持对网络数据的同步或异步访问,它可被视为在数据来源端和接收端之间架设了一个数据通道.,1.4 网络流(续),对于NetworkStream流,写入操作是指从来源端内存缓冲区到网络上的数据传输;读取操作是从网络上到接收端内存缓冲区(如字节数组)的数据传输。构造NetworkStream对象的常用形式为:Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);NetWorkStream networkStream=new NetworkStream(socket);一旦构造了一个NetworkStream对象,就不需要使用Socket对象了。,