今天我们来看一下在C#中怎样实现服务端与客户端进行交互,具体怎么交互通过一个小程序来体现。要实现这么一个简单的小程序,其中涉及到的技术点虽然不多,但理解起来确实有点困难,其中设计到委托、多线程、TCP/IP网络编程等几个技术点,先对这几个技术点简单介绍下。鉴于本人技术有限,难登大雅之堂,个人表述难免有所错误,敬请见谅。
我们知道方法是没有类型的,不能当做参数进行传递,而委托可将一个方法绑定,使它可以作为参数传递。
操作系统使用进程将它们正在执行的不同应用程序分开。线程是操作系统分配处理器时间的基本单元,并且进程中可以有多个线程同时执行代码。
TCP/IP(Transmission Control Protocol/Internet Protocol)的简写,中文译名为传输控制协议/网际协议,又叫网络通讯协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。TCP/IP 是供已连接因特网的计算机进行通信的通信协议。TCP/IP 定义了设备(并非只有计算机)如何连入因特网,以及数据如何在它们之间传输的标准。
我们知道TCP和UDP服务通常有一个客户/服务器的关系,例如,一个Telnet服务进程开始在系统上处于空闲状态,等待着连接。用户使用Telnet客户程序与服务进程建立一个连接。客户程序向服务进程写入信息,服务进程读出信息并发出响应,客户程序读出响应并向用户报告。因而,这个连接是双工的,可以用来进行读写。
两个系统间的多重Telnet连接是如何相互确认并协调一致呢?TCP或UDP连接唯一地使用每个信息中的如下四项进行确认:
- 源IP地址:发送包的IP地址。
- 目的IP地址:接收包的IP地址。
- 源端口:源系统上的连接的端口。
- 目的端口:目的系统上的连接的端口。
端口是一个软件结构,被客户程序或服务进程用来发送和接收信息。一个端口对应一个16比特的数。服务进程通常使用一个固定的端口,例如,SMTP使用25。这些端口号是‘广为人知’的,因为在建立与特定的主机或服务的连接时,需要这些地址和目的地址进行通讯。
好了,了解这些以后,开始回到咱们的小程序,这个程序包含服务端(可接收客户端信息,并响应客户端)和客户端(可接收服务端信息,并响应服务端),开始写程序之前首先要引用下面这些引用空间
现在来创建服务端,并且侦听等待客户端连接
从客户端获得数据流怎样才能读到呢?我们用微软专门定义的一个读数据流操作StreamReader这个类,当然与之相对应的就是写数据流操作StreamWriter类了。
做完这一步,就可以来实现接收客户端发送的信息了。我们可以定义一个方法专门来接收客户端的信息(当然也可以写在主函数里面,为了后面的操作最好还是写一个方法)。
由于Main()方法是静态的,所以我们将接收客户端信息方法定义成参数,为了使服务端程序能读、能响应客户端并且相互并不影响,。为了使程序能一直运行,所以用死循环来控制,也就不用去关闭流(当然在正常操作下还是要记得关闭流)。
有了接收的方法,再去定义一个响应方法,与接收方法类似
与接收方法不同是响应方法接收的参数是Object类型,这是因为为了使接收与响应能并发执行,需要给响应方法创建一个线程,创建线程需要委托,而线程委托只有两个类型,一个是无参的,一个是参数类型是object类型的,而又需要传送一个流对象,只能定义object类型。
到了这一步服务端基本算是构建完成,现在在回到Main()方法,开始调用接收方法与响应线程:
好了,服务端完成了。然后在构建客户端,客户端与服务端没有多大区别,除了不用TcpListener侦听连接,基本上没多大区别。
先看客户端主函数:
接收服务端信息:
响应服务端:
到这一步,本程序就告一段落了。下面看一下运行结果(首先要先启动服务端,在运行客户端):
到这里就该结束了,由于时间及篇幅有限,本程序仅实现了一个服务端/客户端模式。感兴趣的朋友可以对该程序完善一下,实现一个服务端可以连接多个客户端,实现服务端广播。