c#网络编程之------------Socket编程基础

Socket 编程基础

本章以 Berkeley Socket 为主,主要介绍网络编程时常用的调用和程序使用它们的方法及基本结构。网络编程有两种主要的编程接口,一种是 Berkeley UNIX ( BSD UNIX )的 socket 编程接口,另一种是 AT&T 的 TLI 接口(用于 UNIXSYSV )。

** 1 ** 、 ** TCP/IP ** ** 基础知识 ** ** **

这里先假定读者对 ISO 的 OSI 七层模型已有了一定的了解,下面我们来看看 TCP/IP 模型。 ISO 的 OSI 对服务、接口和协议的概念区别十分明了,但它却没有真正的用户群。 TCP/IP 模型对服务、接口和协议的概念区别不象 OSI 模型那样明晰,但很实用。 TCP/IP 模型分为四层,对应于 OSI 七层模型如下图所示:图 6-1 TCP/IP 参考模型与 OSI 模型的近似对应关系在 TCP/IP 模型中,互联网层是基于无连接互联网络层的分组交换网络。在这一层中主机可以把报文( Packet )发往任何网络,报文独立地传向目标。互联网层定义了报文的格式和协议,这就是 IP 协议族( Internet Protocol )。互联网层的功能是将报文发送到目的地,主要的设计问题是报文路由和避免阻塞。互联网层上面是传输层,该层的主要功能和 OSI 模型的该层一样,主要使源和目的主机之间可以进行会话。该层定义了两个端到端的协议,一个是面向连接的传输控制协议 TCP ,另一个是无连接的用户数据报协议 UDP 。 TCP/IP 协议模型中没有会话层和表示层。传输层之上是应用层,它包含所有的高层协议,如远程虚拟终端协议 TELNET 、文件传输协议 FTP 、简单邮件传输协议 SMTP 等。这些高层协议中常见的如 TELNET 协议,用来允许用户远程登录到另一台 UNIX 机器; FTP 协议用来传输文件,常见的有 WU-FTP ( Washington University 的 FTP 服务器端程序,是一个免费程序); SMTP 协议用来传送 email ,常见的服务器端程序有 netscape 等公司制作的程序,也有免费使用的 sendmail 程序;还有域名系统服务 DNS 协议,新闻组传送协议 NNTP ,用于 WWW 的超文本传输协议 HTTP 等。主机到网络这一层,在 TCP/IP 模型中没有详细定义,这里不作介绍。

** 2 ** ** 、 ** ** Socket ** ** 一般描述 ** ** **

由于越来越多的计算机厂商,特别是工作站制造商如 Sun 等公司采用了 Berkeley UNIX , socket 接口被广泛采用,以至于现在, socket 接口被广泛认可并成为了事实上的工业标准。目前的 SYSV 、 BSD 、 OSF 都将 socket 接口作为系统的一部分。当时设计如何支持 TCP/IP 协议时,有两种加入函数的方法,一种是直接加入支持 TCP/IP 协议的调用,另一种是加入支持一般网络协议的函数,而用参数来指定支持 TCP/IP 协议。 Berkeley 采用了后者,这样可以支持多协议族, TCP/IP 是协议族之一( PF_INET )。

** 2.1 socket ** ** 描述符 ** ** **

前面已经提到过,在 UNIX 中,进程要对文件进行操作,一般使用 open 调用打开一个文件进行访问,每个进程都有一个文件描述符表,该表中存放打开的文件描述符。用户使用 open 等调用得到的文件描述符其实是文件描述符在该表中的索引号,该表项的内容是一个指向文件表的指针。应用程序只要使用该描述符就可以对指定文件进行操作。同样, socket 接口增加了网络通信操作的抽象定义,与文件操作一样,每个打开的 socket 都对应一个整数,我们称它为 socket 描述符,该整数也是 socket 描述符在文件描述符表中的索引值。但 socket 描述符在描述符表中的表项并不指向文件表,而是指向一个与该 socket 有关的数据结构。 BSD UNIX 中新增加了一个 socket 调用,应用程序可以调用它来新建一个 socket 描述符,注意进程用 open 只能产生文件描述符,而不能产生 socket 描述符。 socket 调用只能完成建立通信的部分工作,一旦建立了一个 socket ,应用程序可以使用其他特定的调用来为它添加其他详细信息,以完成建立通信的过程。

** 2.2 ** ** 从概念上理解 ** ** socket ** ** 的使用网络编程中最常见的是客户 ** ** / ** ** 服务器模式。 ** ** **

以该模式编程时,服务端有一个进程(或多个进程)在指定的端口等待客户来连接,服务程序等待客户的连接信息,一旦连接上之后,就可以按设计的数据交换方法和格式进行数据传输。客户端在需要的时刻发出向服务端的连接请求。

这里为了便于理解,提到了这些调用及其大致的功能。使用 socket 调用后,仅产生了一个可以使用的 socket 描述符,这时还不能进行通信,还要使用其他的调用,以使得 socket 所指的结构中使用的信息被填写完。在使用 TCP 协议时,一般服务端进程先使用 socket 调用得到一个描述符,然后使用 bind 调用将一个名字与 socket 描述符连接起来,对于 Internet 域就是将 Internet 地址联编到 socket 。之后,服务端使用 listen 调用指出等待服务请求队列的长度。然后就可以使用 accept 调用等待客户端发起连接(一般是阻塞等待连接,后面章节会讲到非阻塞的方式),一旦有客户端发出连接, accept 返回客户的地址信息,并返回一个新的 socket 描述符,该描述符与原先的 socket 有相同的特性,这时服务端就可以使用这个新的 socket 进行读写操作了。一般服务端可能在 accept 返回后创建一个新的进程进行与客户的通信,父进程则再到 accept 调用处等待另一个连接。客户端进程一般先使用 socket 调用得到一个 socket 描述符,然后使用 connect 向指定的服务器上的指定端口发起连接,一旦连接成功返回,就说明已经建立了与服务器的连接,这时就可以通过 socket 描述符进行读写操作了。下面是在客户和服务端使用 TCP 时,客户进程和服务进程使用系统调用的该程。

使用 TCP 的客户和服务端使用系统调用的图示使用无连接的 UDP 协议时,服务端进程创建一个 socket ,之后调用 recvfrom 接收客户端的数据报,然后调用 sendto 将要返回客户端的消息发送给客户进程。客户端也要先创建一个 socket ,再使用 sendto 向服务端进程发出请求,使用 recvfrom 得到返回的消息。

Published At
Categories with Web编程
Tagged with
comments powered by Disqus