Java编程思想-网络编程


一、机器的标识

当然,为了分辨来自别处的一台机器,以及为了保证自己连接的是希望的那台机器,必须有一种机制能独一 无二地标识出网络内的每台机器。早期网络只解决了如何在本地网络环境中为机器提供唯一的名字。但Java 面向的是整个因特网,这要求用一种机制对来自世界各地的机器进行标识。为达到这个目的,我们采用了IP (互联网地址)的概念。IP 以两种形式存在着: (1) 大家最熟悉的DNS(域名服务)形式。我自己的域名是bruceeckel.com。所以假定我在自己的域内有一 台名为Opus的计算机,它的域名就可以是 Opus.bruceeckel.com。这正是大家向其他人发送电子函件时采用 的名字,而且通常集成到一个万维网(WWW)地址里。 (2) 此外,亦可采用“四点”格式,亦即由点号(.)分隔的四组数字,比如202.98.32.111。 不管哪种情况,IP地址在内部都表达成一个由32 个二进制位(bit)构成的数字(注释①),所以IP地址 的每一组数字都不能超过255。利用由java.net 提供的 static InetAddress.getByName(),我们可以让一个 特定的Java 对象表达上述任何一种形式的数字。结果是类型为InetAddress 的一个对象,可用它构成一个 “套接字”(Socket),大家在后面会见到这一点。
①:这意味着最多只能得到40亿左右的数字组合,全世界的人很快就会把它用光。但根据目前正在研究的新
IP编址方案,它将采用128 bit 的数字,这样得到的唯一性IP地址也许在几百年的时间里都不会用完。

二、服务器和客户机

网络最基本的精神就是让两台机器连接到一起,并相互“交谈”或者“沟通”。一旦两台机器都发现了对 方,就可以展开一次令人愉快的双向对话。但它们怎样才能“发现”对方呢?这就象在游乐园里那样:一台 机器不得不停留在一个地方,侦听其他机器说:“嘿,你在哪里呢?” “停留在一个地方”的机器叫作“服务器”(Server);到处“找人”的机器则叫作“客户机”(Client) 或者“客户”。它们之间的区别只有在客户机试图同服务器连接的时候才显得非常明显。一旦连通,就变成
了一种双向通信,谁来扮演服务器或者客户机便显得不那么重要了。

所以服务器的主要任务是侦听建立连接的请求,这是由我们创建的特定服务器对象完成的。而客户机的任务 是试着与一台服务器建立连接,这是由我们创建的特定客户机对象完成的。一旦连接建好,那么无论在服务
器端还是客户机端,连接只是魔术般地变成了一个 IO数据流对象。

三、端口:机器内独一无二的场所

有些时候,一个IP地址并不足以完整标识一个服务器。这是由于在一台物理性的机器中,往往运行着多个服 务器(程序)。由IP 表达的每台机器也包含了“端口”(Port)。我们设置一个客户机或者服务器的时候, 必须选择一个无论客户机还是服务器都认可连接的端口。就象我们去拜会某人时,IP 地址是他居住的房子, 而端口是他在的那个房间。
注意端口并不是机器上一个物理上存在的场所,而是一种软件抽象(主要是为了表述的方便)。客户程序知 道如何通过机器的IP 地址同它连接,但怎样才能同自己真正需要的那种服务连接呢(一般每个端口都运行着 一种服务,一台机器可能提供了多种服务,比如HTTP 和 FTP等等)?端口编号在这里扮演了重要的角色,它 是必需的一种二级定址措施。也就是说,我们请求一个特定的端口,便相当于请求与那个端口编号关联的服 务。“报时”便是服务的一个典型例子。通常,每个服务都同一台特定服务器机器上的一个独一无二的端口 编号关联在一起。客户程序必须事先知道自己要求的那项服务的运行端口号。 系统服务保留了使用端口1 到端口 1024 的权力,所以不应让自己设计的服务占用这些以及其他任何已知正在 使用的端口。本书的第一个例子将使用端口8080(为追忆我的第一台机器使用的老式8 位Intel 8080芯
片,那是一部使用CP/M 操作系统的机子)。

四、套接字

“套接字”或者“插座”(Socket)也是一种软件形式的抽象,用于表达两台机器间一个连接的“终端”。 针对一个特定的连接,每台机器上都有一个“套接字”,可以想象它们之间有一条虚拟的“线缆”。线缆的 每一端都插入一个“套接字”或者“插座”里。当然,机器之间的物理性硬件以及电缆连接都是完全未知 的。抽象的基本宗旨是让我们尽可能不必知道那些细节。 在Java 中,我们创建一个套接字,用它建立与其他机器的连接。从套接字得到的结果是一个 InputStream 以 及OutputStream(若使用恰当的转换器,则分别是Reader 和 Writer),以便将连接作为一个IO流对象对 待。有两个基于数据流的套接字类:ServerSocket,服务器用它“侦听”进入的连接;以及Socket,客户用 它初始一次连接。一旦客户(程序)申请建立一个套接字连接,ServerSocket 就会返回(通过accept()方 法)一个对应的服务器端套接字,以便进行直接通信。从此时起,我们就得到了真正的“套接字-套接字” 连接,可以用同样的方式对待连接的两端,因为它们本来就是相同的!此时可以利用 getInputStream()以及 getOutputStream()从每个套接字产生对应的InputStream 和OutputStream 对象。这些数据流必须封装到缓 冲区内。可按第10章介绍的方法对类进行格式化,就象对待其他任何流对象那样。 对于Java 库的命名机制,ServerSocket(服务器套接字)的使用无疑是容易产生混淆的又一个例证。大家可 能认为ServerSocket 最好叫作“ServerConnector”(服务器连接器),或者其他什么名字,只是不要在其 中安插一个“Socket”。也可能以为ServerSocket和 Socket都应从一些通用的基础类继承。事实上,这两 种类确实包含了几个通用的方法,但还不够资格把它们赋给一个通用的基础类。相反,ServerSocket 的主要 任务是在那里耐心地等候其他机器同它连接,再返回一个实际的Socket。这正是“ServerSocket”这个命名 不恰当的地方,因为它的目标不是真的成为一个Socket,而是在其他人同它连接的时候产生一个Socket 对 象。
然而,ServerSocket确实会在主机上创建一个物理性的“服务器”或者侦听用的套接字。这个套接字会侦听 进入的连接,然后利用 accept()方法返回一个“已建立”套接字(本地和远程端点均已定义)。容易混淆的 地方是这两个套接字(侦听和已建立)都与相同的服务器套接字关联在一起。侦听套接字只能接收新的连接 请求,不能接收实际的数据包。所以尽管ServerSocket 对于编程并无太大的意义,但它确实是“物理性” 的。
创建一个ServerSocket时,只需为其赋予一个端口编号。不必把一个 IP 地址分配它,因为它已经在自己代 表的那台机器上了。但在创建一个 Socket时,却必须同时赋予IP 地址以及要连接的端口编号(另一方面,
从ServerSocket.accept()返回的Socket 已经包含了所有这些信息)。

五、POST 的概念

在许多应用程序中使用 GET都没有问题。但是,GET要求通过一个环境变量将自己的数据传递给CGI程序。 但假如GET 字串过长,有些Web服务器可能用光自己的环境空间(若字串长度超过 200字符,就应开始关心 这方面的问题)。CGI为此提供了一个解决方案:POST。通过 POST,数据可以编码,并按与GET 相同的方法 连结起来。但POST 利用标准输入将编码过后的查询字串传递给CGI 程序。我们要做的全部事情就是判断查询 字串的长度,而这个长度已在环境变量CONTENT_LENGTH 中保存好了。一旦知道了长度,就可自由分配存储空
间,并从标准输入中读入指定数量的字符。

总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值