Java就业培训教程第十一章 网络编程.doc
《Java就业培训教程第十一章 网络编程.doc》由会员分享,可在线阅读,更多相关《Java就业培训教程第十一章 网络编程.doc(23页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第11章 网络编程 有人说,20世纪最伟大的发明并不是计算机,而是计算机网络。还有人说,如果你买了计算机而没有联网,就等于买了电话机却没有接电话线一样。计算机网络就是实现了多个计算机互联的系统,相互连接的计算机之间彼此能够进行数据交换。正如城市道路系统总是伴随着城市交通规则来使用的道理,计算机网络总是伴随着计算机网络协议一起使用的。网络协议规定了计算机之间连接的物理、机械(网线与网卡的连接规则)、电气(有效的电平范围)等特性以及计算机之间的相互寻址规则、数据发送冲突的解决、长的数据如何分段传送与接收等。就象不同的城市可能有不同的交通规则一样,目前的网络协议也有多种,其中,TCP/IP协议就是一
2、个非常实用的网络协议,它是Internet所遵循的协议,是一个“既成事实”的标准,已广为人知并且广泛应用在大多数操作系统上,也可用于大多数局域网和广域网上。网络应用程序,就是在已实现了网络互联的不同的计算机上运行的程序,这些程序相互之间可以交换数据。编写网络应用程序,首先必须明确网络程序所要使用的网络协议,TCP/IP是网络应用程序的首选协议,大多数网络程序都是以这个协议为基础,本章关于网络程序编写的讲解,都是基于TCP/IP协议的。11.1 网络编程的基础知识11.1.1 TCP/IP网络程序的IP地址和端口号要想让网络中的计算机能够互相通信,必须为每台计算机指定一个标识号,通过这个标识号来
3、指定要接收数据的计算机和识别发送数据的计算机,在TCP/IP协议中,这个标识号就是IP地址,目前IP地址在计算机中用四个字节,也就是32位的二进制数来表示,称为Ipv4。为了便于记忆和使用,我们通常取用每个字节的十进制数,并且每个字节之间用圆点隔开的文本格式来表示IP地址,如192.168.8.1。随着计算机网络规模的不断扩大,用四个字节来表示IP地址已越来越不敷使用,人们正在实验和定制使用16个字节表示IP地址的格式,这就是Ipv6。由于Ipv6还没有投入使用,现在网络上用的还都是Ipv4,我们这里的知识也只围绕着Ipv4来展开。因为一台计算机上可同时运行多个网络程序,IP地址只能保证把数据
4、送到该计算机,但不能保证把这些数据交给哪个网络程序,因此,每个被发送的网络数据包的头部都包含有一个称为端口的部分,它是一个整数,用于表示该数据帧交给哪个应用程序来处理。我们还必须为网络程序指定一个端口号,不同的应用程序接收不同端口上的数据,同一台计算机上不能有两个使用同一端口的程序运行。端口数范围为0-65535之间。0-1023之间的端口数是用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,从而避免端口号已被另一个应用或系统服务所用。如果我们的一个网络程序指定了自己所用的端口号为3150,那么其他网络程序发送给这个网络程序的数据包中必须指明接收程序的端口号为3
5、150,当数据到达第一个网络程序所在的计算机后,驱动程序根据数据包中的3150这个端口号,就知道要将这个数据包交给这个网络程序。11.1.2 UDP与TCP在TCP/IP协议栈中,有两个高级协议是我们网络应用程序编写者应该了解的,它们是传输控制协议(Transmission Control Protocol,简称TCP)和用户数据报协议(User Datagram Protocol,简称UDP)。TCP是面向连接的通信协议,TCP提供两台计算机之间的可靠无错的数据传输。应用程序利用TCP进行通信时,源和目标之间会建立一个虚拟连接。这个连接一旦建立,两台计算机之间就可以把数据当作一个双向字节流进
6、行交换。就像我们打电话一样,互相能听到对方的说话,也知道对方的回应是什么。UDP是无连接通信协议,UDP不保证可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。简单地说,如果一个主机向另外一台主机发送数据,这一数据就会立即发出,而不管另外一台主机是否已准备接收数据。如果另外一台主机收到了数据,它不会确认收到与否。就像传呼台给用户发信息一样,传呼台并不知道你是否能收到信息(为了避免丢失用户信息,他们常常将一条信息发送两遍)。TCP、UDP数据包(也叫数据帧)的基本格式如图11.1所示。图11.111.1.3 Socket大家不要生硬和孤立地去理解什么是Socket,就象我们不要
7、让一个从来没有见到过大米与米饭的人去理解什么是“rice”一样的道理,任何一个事物和概念都得有个代名词,大家只有先理解和事物和概念本身,就自然理解了它的代名词。同样Socket是网络驱动层提供给应用程序编程的接口和一种机制,大家先掌握和理解了这个机制,自然就明白了什么是Socket。大家可以认为Socket是应用程序创建的一个港口码头,应用程序只要把装着货物的集装箱(在程序中就是要通过网络发送的数据)放到港口码头上,就算完成了货物的运送,剩下来的工作就由货运公司去处理了(在计算机中由驱动程序来充当货运公司)。对接收方来说,应用程序也要创建的一个港口码头,然后就一直等待到该码头的货物到达,最后从
8、码头上取走货物(发给该应用程序的数据)。 Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的Ip和Port。此后,应用程序送给Socket的数据,由Socket交给驱动程序向网络上发送出去。计算机从网络上收到与该Socket绑定的IP+Port相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据。网络应用程序就是这样通过Socket进行数据的发送与接收的。作者用下面的两个图例来帮助读者理解应用程序、Socket、网络驱动程序之间的数据传送过程与工作关系。1数据发送过程如图11.2所示:图11.22数据接收过程如图11.3所示:
9、图11.3Java分别为UDP和TCP两种通信协议提供了相应的编程类,这些类存放在 包中,与UDP对应的是DatagramSocket,与TCP对应的是ServerSocket(用于服务器端)和Socket(用于客户端)。网络通信,更确切的说,不是两台计算机之间在收发数据,而是两个网络程序之间在收发数据,我们也可以在一台计算机上进行两个网络程序之间的通信,这两个程序要使用不同的端口号。11.2 Java编写UDP网络程序11.2.1 DatagramSocket编写UDP网络程序,我们首先要用到.DatagramSocket类,通过查阅JDK文档资料,看到DatagramSocket类的构造函
10、数主要有如下几种形式:public DatagramSocket() throws SocketExceptionpublic DatagramSocket(intport) throws SocketExceptionpublic DatagramSocket(intport,InetAddressladdr) throws SocketException用第一个构造函数创建DatagramSocket对象,没有指定端口号,系统就会为我们分配一个还没有被其他网络程序所使用的端口号。用第二个构造函数创建DatagramSocket对象,我们就可以指定自己想要的端口号。用第三个构造函数创建Dat
11、agramSocket对象,我们除了指定自己想要的端口号外,还可以指定相关的IP地址,这种情况适用于计算机上有多块网卡和多个IP的情况,我们可以明确规定我们的数据通过哪块网卡向外发送和接收哪块网卡收到的数据。如果在创建DatagramSocket对象时,我们没有指定网卡的IP地址,在发送数据时,底层驱动程序会为我们选择其中一块网卡去发送,在接收数据时,我们会接收到所有网卡收到的与程序端口一致的数据,对于我们一般只有一块网卡的情况,我们就不用专门指定了,发送和接收时肯定都是它了。其实,对于只有一块网卡的情况,在这里指定了IP地址,反而会给我们的程序带来很大的不方便,你的这个网络程序只能在具有这个
12、IP地址的计算机上运行,而不能在其他的计算机上运行。当我们编写发送程序时,用哪个构造函数呢?我们在创建时DatagramSocket对象时,不指定端口号,系统就会为我们分配一个端口号,因此,我们可以用第一个构造函数,这样就相当于你给别人打电话时,你的电话可以是任意的,最好不要固定,如果你非要用某个电话,那当别人正在用这个电话时,你就只有干等的份了。但作为接收程序,我们必须自己指定一个端口号,而不要让系统随机分配,我们可以用第二个构造函数,否则,我们就不能在程序运行前知道我们的端口号,并且每一次运行所分配的端口号都不一样,就象有朋友让你给他打电话,可他的电话号码不确定是不行的。 如果我们的程序不
13、再使用某个Socket,我们应该调用DatagramSocket.close()方法,关闭这个Socket,通知驱动程序释放为这个Socket所保留的资源,系统就可以将这个Socket所占用的端口号重新分配给其他程序使用。在发送数据时,我们用Datagram.send()方法,其完整的格式如下:public void send(DatagramPacketp) throws IOException在要接收数据时,我们用Datagram.receive()方法,其完整的格式如下:public void receive(DatagramPacketp) throws IOExceptionData
14、gram.send()和Datagram.receive()方法都需要我们传递一个DatagramPacket类的实例对象,如果把DatagramSocket比作创建的港口码头,那么DatagramPacket就是我们发送和接收数据的集装箱。11.2.2 DatagramPacket查阅JDK文档,DatagramPacket类的构造函数主要有如下几种形式:public DatagramPacket(bytebuf,intlength)public DatagramPacket(bytebuf,intlength,InetAddressaddress,intport)用第一个构造函数创建的Da
15、tagramPakcet对象,只指定了数据包的内存空间和大小,相当于只定义了集装箱的大小。用第二个构造函数创建的DatagramPacket对象,不仅指定了数据包的内存空间和大小,而且指定了数据包的目标地址和端口。在接收数据时,我们是没法事先就知道哪个地址和端口的Socket会给我们发来数据,就象我们要准备一个集装箱去接收发给我们的货物时,是不用标明发货人或是收货人的地址信息的,所以我们应该用第一个构造函数来创建接收数据的DatagramPakcet对象。在发送数据时,我们必须指定接收方Socket的地址和端口号,就象我们要发送数据的集装箱上面必须标明接收人的地址信息一样的道理,所以我们应该用
16、第二个构造函数来创建发送数据的DatagramPakcet对象。11.2.3 InetAddress在发送数据时,DatagramPacket构造方法需要我们传递一个InetAddress类的实例对象,InetAddress是用于表示计算机地址的一个类,我们习惯上表示计算机地址是用“192.168.0.1”或“www.it315.org”的字符串格式,我们现在要做的就是根据这种习惯上的字符串地址格式来创建一个InetAddress类的实例对象,查阅JDK文档资料资料,我们发现InetAddress.getByName()这个静态方法能够根据我们的条件返回一个InetAddress类的实例对象。
17、另外,当我们将数据接收到DatagramPacket对象中后,我们想知道发送方的IP地址和端口号,该怎么办呢?到现在为止,我们应该学会了解决类似这样的小问题的最基本的思路了,大家应该很容易想到在JDK文档中去查DatagramPacket类的方法,看其中有没有解决我们问题的方法。在JDK文档中,我们又看到了DatagramPacket.getInetAddress()和DatagramPacket.getPort()方法。getInetAddress方法返回的是InetAddress类型的对象,我们需要将它转换成用点(.)隔开的字符串型的IP地址。在JDK文档中去查InetAddress类的帮
18、助,我们又可以看到InetAddress.getHostAddress方法能够以字符串的形式返回InetAddress对象中的IP地址。11.2.4 最简单的UDP程序有了前面这些网络编程的基本知识,我们接下来编写两个最简单的UDP程序,在一台计算机上相互发送和接收数据,接收程序所用的端口号为3000,发送程序的端口号由系统分配,这里假设运行程序的计算机的IP地址是192.168.0.213,读者应根据将程序中的这个地址,修改成你的计算机的实际地址后,编译运行。发送程序:UdpSend.javaimport .*;public class UdpSendpublic static void m
19、ain(String args) throws ExceptionDatagramSocket ds=new DatagramSocket();String str=“hello world”;DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(),InetAddress.getByName(“192.168.0.213”),3000);ds.send(dp);ds.close();接收程序:UdpRecv.javaimport .*;public class UdpRecvpublic static void main
20、(String args) throws ExceptionDatagramSocketds=new DatagramSocket(3000);byte buf=new byte1024;DatagramPacket dp=new DatagramPacket(buf,1024);ds.receive(dp);String strRecv=new String(dp.getData(),0,dp.getLength() + “ from ” + dp.getAddress().getHostAddress()+”:”+dp.getPort(); System.out.println(strRe
21、cv);ds.close();由于创建DatagramPacket时,要求的数据格式都是byte型的数组,所以程序在发送数据时用到了String.getBytes()方法将字符串转换成byte型的数组,在接收数据时用到了String类的public String(bytebytes, intoffset, intlength)构造方法,将byte型的数组转换成字符串。我们为什么不用public String(bytebytes)构造方法来将byte型的数组转换成字符串呢?因为我们在接收数据前,是没法知道对方实际发送的数据包的长度的,因此,在程序中定义buf数组具有1024个字节,即表示我们能够
22、接收的数据包的大小最多为1024个字节,也就是确信对方每次发送的数据包不会超过1024个字节的。对方发送的数据的大小是不确定的,往往都不可能正好是1024个字节,如上面程序中,我们只收到的“hello world”,只有11个字节的数据,public String(bytebytes)是将数组中的所有元素都转换成字符串,即将这1024个字节都转换成字符串,包括那些根本没有被添充的单元。public String(bytebytes, intoffset, intlength)是将字节数组中从offset开始,往后一共length个单元的内容转换成字符串,DatagramPacket.getLe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Java就业培训教程第十一章 网络编程 Java 就业 培训 教程 第十一 网络 编程
限制150内