网络编程基本概念

时间:2022-12-15 08:12:26

网络编程基本概念

.NET框架SYstem.Net.*命名空间下提供了一系列的类用于网络通信.从层次上来说,这些类可以分为两组,一组位于System.Net.Sockets命名空间下,提供底层的,基于传输层协议的通信,TCP,UDP;一组位于System.Net命名空间下,提供高层的,一局应用层协议的通信,HTTP,FTP,SMTP.

 

好长时间没写点东西了,都快忘了我还有作家这一职位了,哈哈.其实我是一个作家...

 

 

 

面向连接的传输协议----TCP

 

我以前说过关于TCP的内容,在协议里面,这里不打算多说了,我单纯的说一点关于TCP协议的特点.

 

首先要知道的是TCP是面向连接的,也就是说两个远程主机(或者叫进程,远程通信实际上是进程之间的通信,进程是指运行中的程序)必须首先进行一个握手过程,确认连接成功之后才能传输实际的数据.比如,进程A想要将字符创”Hello”发送给进程B,他首先要建立连接.在这一过程中,进程A首先需要知道进程B的位置(主机地址和端口号).随后发送一个不包含实际数据的请求报文,可将这个报文称之为”hi”.如果进程B接收到这个”hi”,就向A回复一个”hi”,进程A随后才发送实际的数据”hello”.

 

关于TCP,第二点需要了解的是它是全双工的,如果两个主机上的进程,AB之间建立好连接,那么数据就可以从AB,也可以从BA.除此之外,TCP还是点对点的,意思是说一个TCP连接总是两者之间的,在发送中,通过一个连接将数据发给多个接收方是不可能的.如果想让数据发给多个接收方,就需要创建多个链接.

 

TCP最重要的一个特性应该是可靠性吧,意思说连接建立后,数据的发送一定能够到达,并且是有序的.如果发送方发送了ABC,那么接收方收到的也一定是ABC,而不是别的顺序.

 

在编程中,TCP相关的就是套接字(Socket).TCP是属于传输层协议,这个大家应该知道吧,OSI?知道吗?如何从应用程序中获取来自传输层的数据呢?通过套接字.套接字像是传输层打开的一扇门,应用程序通过这扇门向远程发送数据,或者接受来自远程的数据.这个门后面的事情,比如消息是如何传递的,是如何保证可靠性的,开发者是不需要关心的,这属于网络底层的事情.开发者需要关心和处理的是经过这扇门传递到应用程序中的数据.

 

如果想写封信给远方的朋友,信中的内容需要你自己写,而当将信投入到邮筒中的时候,邮筒的那个口就相当于套接字,信在进入邮筒之后就是其他人的事了,不需要你参与了.我们从来不会去关心信是如何从你这里到你朋友那里的,只要写好了投入邮箱就可以了.

 

两个应用程序之间的对话是通过套接字这个出入口来完成的,实际上套接字包含的最重要的就是两个信息:发出连接的本地IP地址和端口号,连接到的远程IP地址和端口号.

 

这里又出现了端口号这个名词,一般来说计算机同时运行着非常多的应用程序,它们可能需要同远程主机打交道,所以远程主机就需要有一个ID来标示它想与本地机器上的哪个应用程序打交道,这里的ID就是端口.将端口分配给一个应用程序,这样来自这个端口的数据总是针对这个应用程序的.有一个很形象的例子可以说明这个问题:可以将主机地址想象成电话号码,将端口号想象成分机号码.

 

.NET,提供了System.Net.Sockets.Cosket,通过它可以直接对套接字进行编程.同时.NET还提供了两个帮助类对套接字进行了包装,使得操作变得更加简单,这两个类时TcpClientTcpListener.

 

通过名字就能看出来,TcpListener用于接收连接请求,TcpClient用于接收和发送数据.TcpListener持续的保持对端口的监听,一旦受到一个连接请求后,就额可以获得一个TcpClient对象,而数据的发送和接收都是由TcpClient完成的.此时,TcpListener并没有停止工作,他继续保持对端口的监听,以应对新的连接请求.

 

现在有这样一种情况:两台主机,AB,起初他们彼此独立.当他们想要进行数据通信时,需要一方发起连接,另一方则要对本机的某一端口进行侦听.在监听方收到连接请求,并建立连接后,它们之间就可以进行数据通信了.发起连接的一方并不需要进行监听.因为连接数全双工的,可以使用已经建立的连接进行数据收发.在前面说过了,将发起连接的一方叫做客户端,另一端叫做服务端,现在可以得出:总是在服务端使用TcpListener,因为他需要建立起一个初始的连接.

 

即时通信程序的三种模式

 

网络编程的一个最常见的的应用就是即时通信程序.

 

先来看一下点对点模式

 

当采用这种模式时,每台计算机即是客户端也是服务端,因为他需要进行端口的监听.实现这个模式的难点是:各个主机之间如何知道其他主机的存在?此时通常的做法是当某一个主机上线时,通过UDP协议进行一个IP广播,使用这个方式来通知其他主机自己已经上线并说明位置,收到广播的主机发挥一个应答,此时主机便知道其他主机的存在,然后便可以进行连接和通信.

 

第二种模式引入了服务器,这种方式解决了上面判断有多少主机在线的问题.由服务器来专门进行广播.服务器持续保持对端口的监听状态,每当有主机上线时,首先连接到服务器,服务器收到连接后,将该主机的IP地址和端口号发往其他在线主机.这样其他主机便知道该主机已上线,并知道其所在位置,从而可以进行连接和对话.在服务器进行了广播之后,因为各个主机已经知道了其他主机的位置,因为主机之间的对话就不在通过服务器了,而是直接进行连接.因为,使用这种模式各个主机依然需要保持对端口的监听.

 

第三种模式是最简单的一种也是最实用的一种,主机的登陆与离线与第二种模式类似,由服务器进行广播,但是区别是每台主机在上线时就与服务器建立了连接,彼此并不建立连接,那么当从主机A向主机B发送消息时,就需要通过这样一条路径:A->服务器->B,通过这种方式,各个主机不需要再对端口进行监听,只需要服务器对端口进行监听就够了.

 

对于一些较大的文件,比如图片或者文件,如果想从A发往B,以服务器为中介进行传输效率会很低,此时可以临时搭建一个主机AB的连接,用于传输大文件.当文件传输结束后再关闭连接.为啥么不能一直开着?而是用了之后立马抛弃呢?

 

除此之外,由于消息都经过服务器,因此服务器还可以缓存主机之间的对话,即当A发送B,如果B离线,服务器可以对消息进行缓存,当主机B上线的时候连接到服务器,服务器自动将缓存的消息发往B.

 

理论就说这么多,下面开始讲解代码.