Java开发综合实战 教案 项目八 网络编程基础_第1页
Java开发综合实战 教案 项目八 网络编程基础_第2页
Java开发综合实战 教案 项目八 网络编程基础_第3页
Java开发综合实战 教案 项目八 网络编程基础_第4页
Java开发综合实战 教案 项目八 网络编程基础_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

项目八

网络编程基础

思政目标

A理论联系实际,培养举一反三、触类旁通的学习能力。

A追根溯源,从基础着手,培养科学严谨的思维方式。

技能目标

>能够实现简单的TCP网络通信

>能够实现简单的UDP网络通信

项目导读

将物理位置不同、且具有独立功能的多台计算机连接在一起

就形成r网络。网络可以使不司物理位置上的计算机进行资源共

享和通信。Java提供了专门的网络开发程序包java.net,包含网

络程序所需要的不同的类。用户只要创建这些类的对象,调用相应

的方法,即使不具备有关的网络知识,也可以编写出网络通信程

序。

201

Java开发综合实战

任务1网络程序设计基础

任务引入

通过前面几个项目的学习,小白已逐步完成了一个简易的单机版进销存管理系统。

考虑到应用程序的实用性,小白想将单机版的管理系统扩展为网络版程序。在此之前,他

有必要先了解网络应用程序常用的设计模式、常用的网络协议,以及IP地址和端口的概

念。

箪?知识法备]

一、网络应用程序设计模式

在网络通信过程中往往会分为两种端点:服务端与客户端,围绕这两种端点产生了

网络程序开发的两种模式C/S模式和B/S模式。在开发过程中,应根据实际需求,并结

合各种模式的特点选择应用程序设计模式。

1.C/S(Client/Server,客户端/服务端)模式।

这种模式将网络事务处理分为客户端和服务器端两个部分。客户端用于为用户提供

操作,同时向网络提供请求服务的接口;服务端负责接收并处理客户端发出的服务请求,

并将服务处理结果返回给客户端。因此,这种模式要开发两套程序,一套是客户端,另一

套是服务端。在进行维护时,也需要维护两套程序,而且客户端的程序史新也必须及时。

C/S模式的主要特点是交互性强,具有安全的存取模式、网络通信量低、响应速度快,程

序安全性能好。

2.B/S(Browser/Server,浏览器/服务器)模式

这种模式是伴随着Internet技术的兴起,对C/S模式的改进,仅使用HTP进行通

信,主要事务逻辑在服务器端实现,无须安装客户端,Web浏览器即客户端,因此只需

针对服务器端开发一套程序。这种程序在日后进行程序维护时只需维护服务器端即可,

分布性强,开发简单,维护方便。但此类程序使用公共端口,包括公共协议,所以安全性

很差,对于实现复杂的应用构造也有较大的困难。

二、常用的网络协议

从应用的角度出发,网络协议可理解为网络通信规则,是网络中的各台主机传输数

据进行通信的规则说明,规定了计算机之间连接的特征、相互寻址规则、数据发送冲突的

解决方式、数据传送与接收的方式等内容。

网络通信协议有很多,目前应用最广泛的是TC"IP、UDP、ICMP和其他一些协议的

202

项目八网络编程基础

协议族。本节简单地介绍本项目的网络编程主要涉及的TCP、UDP和IP。

1.TCP协议

TCP(TransmissionControlProtocol,传输控制协议)提供两台计算机之间可靠的

数据传送,也就是说,可以保证数据能够确实送达,而且抵达的数据的排列顺序和送出时

的顺序相同。因此,TCP协议常用于可靠性要求比较高的场合。

2.UDP协议

UDP(UserDatagramProtocol,用户数据报协议)是无连接通信协议,以独立发送

数据报的方式向若干个目标发送数据,或接收来自若干个源的数据,不保证数据的可靠

传输。也就是说,数据不一定能送达,抵达的数据的排列顺序和送出时的顺序也不一定相

同。因此,IDP协议适用于一些对数据准确性要求不高,但对传输速度和时效性要求非常

高的网站。

3.TCP/IP协议

TCP/IP(TransmissionControlProtoco1/InternetProtocol传输控制协议/网际

协议)是Inlernel最基本的通信协议,在全球范围内实现了不同硬件结构、不同操作系

统、不同网络系统之间的互联。其中的每台主机都用网络为其分配的Internet地址(即

IP地址)进行唯一标识。

在这里要提请读者注意的是,TCP/IP协议不仅仅指的是TCP和IP两个协议,而是

指能够在多个不同网络间实现信息传输的协议簇,由FTP、SMTP、TCP、UDP、IP等协议构

成。由于TCP/IP协议中TCP协议和IP协议最具代表性,所以被称为TCP/IP协议。

TCP/IP协议共分为4层,分别为应用层、传输层、网络层和数据链路层。各层实现

特定的功能,提供特定的服务和访问接口,并具有相对的独立性,如图8—1所示。

应用程序,Telnet、FTP、SMTP等

可靠的传递服务,TCP和UDP

无连接分组投递服务,IP、ICMP和IGMP

物理层、网络接口层,设备驱动程序及接口卡

图8—1TCP/IP层次结构

三、IP地址和端口

Internet上的主机有两种方式表示地址:域名和IP地址。域名容易记忆,在连接网

络时输入一个主机的域名(例如WWW.baidu.com.cn)后,域名服务器(DNS)负责将域名

转化成IP地址,这样才能和主机建立连接。

在TCP/IP中,IP地址用于唯一地标识一台接收或发送数据的计算机。目前,广泛

使用的IP地址版本是IA4,用4个字节的二进制数表示。为便于记忆和处理,通常将IP

地址写成十进制的形式,每个字节用一个十进制数字(0〜255)表示,数字之间用符号

分开,如127.0.0」,该地址表示本机IP地址,通常用于测试本机TCP/IP是否正

203

项目八网络编程基础

知识准备

在Java中,TCP网络程序设计是指利用Socket类编写通信程序,使用此类可以方便

地建立可靠的、双向的、持续的、点对点的通信连接。利用TCP协议进行通信的两个应用

程序是有主次之分的,一个称为服务器端程序,另一个称为客户端程序,两者的功能和编

写方法大不一样。

通信时,首先要创建代表服务器端的ServerSocket对象,开启一个服务,此服务会

等待客户端的连接请求;然后创建代表客户端的Socket对象,向服务器端发出连接请求,

服务器端响应请求后,两者才建立连接,通过套接字的I/O流开始通信。通信完毕后,使

用套接字的close()方法关闭连接。

一、实现服务器端程序

ServerSocket类的实例对象用于实现一个服务器端程序,在指定的端口等待接收客

户端在该端口发送的TC?连接请求。

SprvprSoc.kpt类的构造方法有以卜.几种形式,通常会抛出TOExc.pption异常八

(1)ServerSocket()

创建没有绑定端口的服务器套接字。这种方法创建的ServerSocket对象创建的服务

器端不监听任何端口,因此不能直接使用。后续操作中需要调用bind。方法将其绑定到

指定的端口上,才可以正常使用。

(2)ServerSocket(intport)

创建绑定到特定端口的服务器套接字。

(3)ServerSocket(intport,intbacklog)

创建绑定到特定端口的服务器套接字,并指定在服务器忙时可以与之保持连接请求

的等待客户数量backlogo

服务器套接字一次可以与一个套接字连接。如果多个客户端同时提出连接请求,服

务器套接字会将请求连接的客户端存入列队中,然后从中取出一个套接字,与服务器新

建的套接字连接起来。如果请求连接数大于队列的最大容纳数(默认大小为50),则多出

的连接请求将被拒绝。

(4)ServerSocket(intport,intbacklog,InctAddressbindAddrcss)

使用指定的端口、侦听backlog和要绑定到的IP地址创建服务器套接字。这种情况

适用于计算机上有多块网卡和多个IP地址的情况,用户可以明确规定ServerSocket在

哪块网卡或哪个IP地址上等待客户的连接请求。

例如,下面的代码使用常用的第(2)种构造方法创建一个绑定到2022端口的服务

器套接字:

try(

ServerSocketserverForClient=newServerSocket(2022);

}catch(lOExceptione){

205

Java开发综合实战

如果2022端口已被占用,就会抛出lOExccption异常。

ServerSocket类的常用方法如表8-2所示。

表8—2ServerSocket类的常用方法

方法说明

Socketaccept()等待并接收客户端连接。如果连接成功,返问一个与发送

请求客户端对应的Socket实例

voidblind(SocketAddressendpoint)将ServerSocket绑定到特定地址

InetAddressgetlnetAddress()获取服务器套按字的本地地址

intgctLocalPort()获取服务器套接字侦听的端口

booleanisBoundO判断服务器套接字的绑定状态

booleanisClosedO返回服务器套接字的关闭状态

voidclose()关闭服务器套接字

创建ServerSocket对象后,如果要接收来自客户端的请求,需要调用ServerSocket

对象的accept。方法获取客户端连接。该方法会阻塞线程的执行,直到服务器端接收到

客户端的连接请求,返回一个与发出请求的客户端Socket对象相连接的Socket对象实

例,程序才叮以向卜继续执行。例如,如果没有接收到客户端的连接请求,第二条语句就

不会执行:

socket=server,accept();

System.out.printIn("Welcome!”);

提示:如果没有客户端请求,accept。方法没有发生阻塞,肯定是程序出现了问题。

通常是使用了一个被其他程序占用的端口号,ServerSocket绑定没有成功。

ServerSocket对象可以调用setSoTimeout(inttimeout)方法设置单位为毫秒的超

时值,一旦ServerSocket对象调用accept()方法阻塞的时间超过timeout,将触发

SocketTimeoutException0

建立连接后,服务器端ServerSocket对象调用getlnetAddress()方法可以获取包含

客户端IP地址和域名的TnetAddess对象;同样,客户端的套接字对象调用

getlnetAddress。方法可以获取包含服务器端IP地址和域名的InetAddess对象。

二、实现客户端程序

Socket类用于实现TCP客户端程序。客户端负责创建连接到服务器的套接字对象,

发出连接请求,井与服务器通佶。

Sockel类的构造方法有以下几种形式,通常会抛出lOException异常。

(1)Socket()

创建没有连接任何服务器的客户端套接字对象c这种方法创建的Socket对象不能直

接使用,后续操作中需要调用connect。方法指定封装了服务器端IP地址和端口号的

SocketAddress对象,才可以与指定的服务器端连接。

(2)Socket(Stringhost,intport)

创建连接到运行在指定地址和端II上的服务器程序的Socket对象。参数host是服

206

项目八网络编程基础

务器的IP地址,port是一个端口号。

(3)Socket(InetAdressaddress,intport)

这种方法与第二种方法类似,创建连接到运行在指定地址和端口上的服务器程序的

Socket对象。

例如,下面的代码使用第(2)种构造方法创建一个连接到服务器的客户端套接字:

try(

Socketclient=newSocket("http:〃192.168.10.110",2022):

}catch(lOExceptione){)

Socket类的常用方法如表8-3所示。

表8—3Socket类的常用方法

方法说明

intgetPort()返回Socket对象与服务器端连接的端口号

InetAddressgetLocalAddress()将Socket对象绑定的本地IP地址封装成InetAddress对

象并返回

InputstreamgetInputstream()获取Socket对象的输入流

OuxputStreamgetOutputStreamO获取Socket对象的输出流

booleanisClosed()判断Socket连接是否已关闭

voidclose()关闭Socket连接,结束本次通信

在关闭Socket连接之前,应先关闭与Socket相关的所有I/O流,以释放相关资源。

三、数据交互通信

客户端创建一个Socket对象向指定的主机和端口发送请求,服务器端的

ServerSocket对象监听客户端在该端口发送的TCP请求。接收到TCP连接请求后,服务

器端的ServerSocket对象调用accept()方法获取客户端连接,并创建一个驻留在服务器

端的Socket实例。客户端Socket与服务器端Socket连接成功后,通过I/O流交互数

据,通过输出流发送数据,通过输入流接收数据,从而实现通信,如图8—2所示。

客户端服务器端

InputstreamInputstream

题据传输

SocketSocket

OutputstreamaOutputstream

图8—2服务器端与客户端的数据交互

客户端Socket对象调用getlnputStreamO方法获得一个输入流,这个输入流指向服

务器端的Socket对象使用getOutputStreamO方法获得的输出流,也就是说,客户端用

207

Java开发综合实战

输入流可以读取服务器写入到输出流中的数据。客户端Socket对象调用

gct()utputStream()方法获得一个输出流,这个输出流的目的地与服务器端的Socket对

象使用gctlnputStreamO方法获得的输入流的源相同,也就是说,客户端通过输出流写

入的数据,服务器通过输入流可以读取。反之亦然,

注意:从Socket连接中读取数据与从文件中读取数据有着很大的不同。从文件中读

取数据时,所有的数据都已经存在文件中。而使用Socket连接时,可能在另一端数据发

送之前,就已经开始读取了,这时,就会阻塞本线程,直到该读取方法成功读取到信息,

本线程才继续执行后续的操作。

双方通信完毕后,Socket对象应调用closeO方法关闭Socket连接。

案例一一模拟问答式交互

本案例利用Socket完成一个TCP程序,模拟向答式交互。

(1)在Eclipse中新建一个名为TCPDcm。的Java项目,然后在其中添加一个名为

TCPServer.java的类,编写服务器端程序,具体代码如下:

importjava.io.DataOutputStrcam;

importjava.io.lOExceptian;

importjava.net.ServerSocket;

importjava.net.Socket;

publicclassTCPServer{

publicstaticvoidmain(String[]args){

ServerSocketserver=null:初始化服务器套接字

Socketsk=null;〃初始化驻留服务器端的套接字

〃服务器端将要输出到客户端的字符串

String[]answers={"你好!我是Server。二匕京","2015年7月31口","冬梦"上

DataOutputStreamout=null;〃初始化输出流

try{

server=newServerSocket(3000);〃创建绑定到3000端II的服务器套接字

}catch(IOExceptione){

System,out.println(e);

)

try(

System.out.printIn("服务器准备就绪,等待客户请求...”);

〃阻塞线程,直到接收到客户端的连接请求,然后为请求创建套接字sk

sk=server,accept();

out=newDataOutputStream(sk.getOutputStreamO);,1'实例化输出流

for(inti=0;i<answers.1ength;i++){

out.writeUTF(answers[i]);〃写入要返回到客户端的消息

208

项目八网络编程基础

Thread.s/eep(1000);〃休眠1秒

)

}catch(Exceptione){〃没有连接请求,捕获异常

System,out.println(e);

}

try{

〃关闭输出流和socket连接

out.close();

sk.closeO;

}catch(Exceptione){}

)

}

(2)在项目中添加一个名为TCPClient的类,编写客户端程序,具体代码如下:

importjava.io.DatalnputStream;

importjava.io.DataOutputStream;

import.Socket;

publicclassTCPC1ient{

publicstaticvoidmain(String口args){

Socketcsk=null;〃声明客户端套接字

〃初始化输入流和输出流

DataInputStreairin=null;

DataOutputStreamout=null;

〃客户端将要发送到服务器端的字符串

String[]questions={"你好!我是Client.哪个城市是世界上首个双奥之城?”,

”北京成功获得2022年冬奥会举办权是哪一天?北京2022年冬残奥会会徽的名字是什么?”};

try(

〃使用客户端Sockel对象也连接到运行在指定地址和端口上的服务器程序

csk=newSocketf127.0.0.1”,3000);

〃如果接收到客户请求,获取客户端的IP地址并输出

Stringaddr=csk.getlnctAddrcss().getllostAddressO;

System.out.printIn(addr+"响应请求”);

〃实例化输入流和输出流

in=newDatalnputStream(csk.getInputstream0);

out=newDataOutputStream(csk.getOutputStreamO);

for(inti=0;i<questions.length;i++){

Systen.out.printin(z/Client|SJ:/z+questions[i]);

Thread.s/eM(500);

209

Java开发综合实战

out.writcUTF(questions[i]);/7写入要发送到服务器端的消息

Stringinstr=in.readUTFO;〃读取服务器端返回的消息,会阻塞状态

Syston.ouC.printlnC'server答:"+instr);输出读取的消息

Thread,s/e改(500);

}

}catch(Exceptione){//连接失败

System.out.printin(e);

)

try{

〃关闭输入流、输出流和socket连接

in.closeO;

out.closeO;

csk.closeO;

}catch(Exceptione){}

)

)

(3)运行TCPServer.java启动服务器,等候客户端的请求,如图8—3所示。然后

运行TCPClient.java,客户端与服务器连接,通过输入流读取服务器返回的消息并输出,

如图8—4所示。

日ConsoleX@DeclarationD□

日ConsoleX岛Declarati...a□-*派|•&地•母驯

图砧翩母喇

■X-1已日▼n▼

<termnated>TCPClient(1)[JavaApplication]D:\S

-日▼F3▼

=«»e^3JA

TCPServer(1)[JavaApplication]D:\R件\e<

Client«)i仁庆盘Client,

芸务器专缶?等符尸,求一-

tit.5servers:体好:我是Server.

Client同:更个w七是M界上口个五具之城:

servers:故

Client闾:北京比5:天用2022=多荚金=分灰悬石一大:

servers:2015=7.531=

ClientiC,北京2022三冬残禹会会名韵^字专一幺?

servers冬》

图8—3服务器端运行效果图8-4客户端运行效果

任务3实现UDP网络程序

210

项目八网络编程基础

任务引入

掌握了TCP网络程序的实现方法,小白想知道常见的UDP程序与TCP程序有哪些异

同,以及实现UDP程序的方法。

知识准备

UDP程序也分为服务器端和客户端两部分。与TCP必须建立可靠连接,提供端到端的

服务不同,UDP是一种面向无连接的协议,UDP服务器为所有通信使用同一套接字,因此,

在通信时发送端和接收端不用建立连接,发送的消息对方不一定能接收到,是相对不可

靠的传输控制协议。

基于UDP通信的基本模式为:将数据打包发送一接收数据报。客户端和服务器端都

使用DatagramPacket对象封装需要发送或者接收的数据,通过DatagramSocket对象的

send。方法和receive。方法发送和接收数据。通信完成后,客户端调用DatagramSocket

实例的close。方法关闭该套接字。

一、发送数据报

UDP通信中,发送数据报的步骤如下:

(1)使用DatagramSocket类的构造方法创建一个数据报套接字。

(2)使用DatagramPacket类的构造方法将要发送的数据封装成数据报。

(3)使用DatagramSocket对象的send。方法发送数据报。

1.创建数据报套接字

Java在java,net包中提供DatagramSocket类用于表示发送或接收数据报的套接字。

在发送端通常使用DatagramSocket类的尢参构造方法DatagramSocket()创建发送端的

数据报套接字,由于没有指定端口号,系统会分配一个没有被占用的端口号。

在客户端创建DatagramSocket实例时,也可以有选择地对本地地址和端口号进行设

置。如果设置了端口号,则客户端会在该端口号上监听从服务器端发送来的数据。在服务

器端创建DatagramSocket实例时,指定本地端口号,并可以有选择地指定本地地址,此

时,服务器已经准备好从任何客户端接收数据。

创建DatagramSocket对象时可能会抛出SocketException异常。

2.创建数据报

Java使用DatagramPacket对象表示数据报,封装UDP逋信中发送或接收的数据。

在创建用于包装待发送的数据的DatagramPacket实例时,要指定要发送到的目的主

机和端口。因此,通常采用以下的构造方法:

DatagramPacket(byte[]data,intlength,InetAddressaddr,intport)

这种方法创建数据报,并指定封装的数据、大小以及数据报的目标IP地址和端口号。

用于将含有data数组的数据封装成数据报,发送到地址为addr的主机的指定端口port。

DatagramPacket类还提供了一些用于获取数据报的内容信息的方法,如表8-4所

不。

211

Java开发综合实战

表8—4DatagramPackct类的常用方法

方法说明

intgetPort()如果是发送端的数据报,则返回接收端的端口号,否则返回发送端的端口号

InetAddress如果是发送端的数据报,则返回接攸端的IP,否则返回发送端的IP

getAddressO

byte[]getDataO如果是发送端的数据报,则返问将要发送的数据,否则返P1将要接收的数据

inigetLenglh()如果是发送端的数据报,则返回将要发送的数据的长度,否则返回将要接收

的数据的长度

3.发送数据报

创建数据报后,使用DatagramSocket对象的send(DatagramPakcetdp)方法,即可

发送指定的数据报dp,该数据报中不仅包含要发送的数据,还包含数据的长度、目标主

机的IP地址和端口号。

发送数据报时可能会产生lOException异常。

二、接收数据报

UDP通信中,接收数据报的步骤如下:

(1)使用DatagramSocket类的构造方法创建一个数据报套接字,绑定到指定的端

口。

(2)使用DatagramPacket类的构造方法创建数据报封装接收到的数据。

(3)使用DatagramSocket对象的receive()方法接收数据报。

1.创建数据报套接字

与发送端不同,接收端的DatagramSocket对象必须指定--个端口号进行监听,不能

是系统随机分配的端口号。创建接收端的数据报套接字可以采用以下两种构造方法:

/DatagramSocket(intport):创建DatagramSocket对象,并将其绑定到本地主

机指定的端口上。

/DatagramSocket(intport,TnetAddressaddress):仓U建DatagramSocket对

象,并将其绑定到指定的本地地址上。这种方法常用于有多块网卡和多个IP地

址的情况。

2.创建接收信息的数据报

在创建用于封装待接收的数据的DatagramPackct实例时,不需要指定数据来源的远

程主机和端口,只需指定一个缓存数据的byte数组即可。通常使用如下的构造方法实现:

DatagramPacket(byte[]data,intlength)

这种方法创建一个%lagramPacket实例,并预先分配空间和大小,以将后续接收到

的数据存放在该空间中。发送数据的源地址和端口等信息会自动包含在DatagramPacket

实例中。

3.接收数据报

使用DatagramSocket对象的receive(DatagrauPakcetdp)方法,即可将接收到的数

据填充到指定的数据报如中。

212

项目八网络编程基础

在接收到数据之前,receive。方法会一直处于阻塞状态,直到接收到数据报才会返

回。因此,如果网络上没有数据发送过来,receive。方法也没有阻塞,肯定是程序中有

问题,大多数情况下是使用了一个被其他程序占用的端口号。

案例一一简易聊天程序

本案例用本地主机的不同端口模拟两台主机互相发送和接收数据报,利用UDP和多

线程技术制作一个简易的聊天程序.

(1)在Eclipse中新建一个名为NetDemo的Java项目,然后在项目中添加一个名

为UserA的类,用于模拟主机A发送和接收数据报,具体代码如下:

importjava.net.Datagrampacket;

importjava.net.DatagramSocket;

importjava.net.InetAddress;

importjava.net.SocketException;

importjava.util.Scanner;

publicclassUserA{

publicstaticvoidmain(String口args){

Scannersc=newScanner(System,in);/创建扫描器

ThreadreadData;//声明线程

ReceiveForAreceiver=newReceiveForA();//创建Runnable实现类对象

DatagramSocketsocketA=null;

try)

readData=newThread(receiver);//创建负责接收信息的线程

readData.start();//启动线程

byte[]buf=newbyte[1];〃定义接收数据的字行数组

Stringstr="127.0.0.1”;〃服务器端IP地址

intport=9000;//服务器端的端口号

//将IP地址封装为InelAddress对象

InetAddressaddr=InetAddress.gelByName(slv);

try(

socketA=newDatagramSocket。;//创建发送端的数据报套接字

}catch(SockctExccptione){}

〃创建数据报,发送到地址为辿I的主机的port端口

DatagramPaikctdp=newDatagramPackot(buf,buf.length,addr,port);

System.out.print(“我对B说:”);

while(sc.hasNext()){//如果输入了内容

Stringinfo=sc.nextLineO;/获取输入的内容

buf=info.getBytcsO;〃将字符串转换为字节数组

213

Java开发综合实战

if(info.length()==0)〃如果没有输入内容

System.exitiff);〃强制关闭JVM,退出程序

buf=info.getBytesO;

dp.setData(buf);〃将字节数组放入数据报打包

socketA.send(dp);//发送数据报

Systen.out.print("我继续对B说:");

)

}catch(Exceptione){捕获异常

System,out.println(e);

)

sc.closeO;

)

)

上面的代码使用hasNext。方法判断是否输入了信息。读者要注意的是,尽管

hasNext()的返回值类型为boolean,但是不会返回false®如果hasNexl()在缓冲区内扫

描到字符就返回iruc,否则会发生阻塞,等待数据输入。因此,在要输入多组数据的情

况下,可以使用while+hasNextO的形式判断是否输入了字符。

(2)在项目中添加一个名为ReceiveForA的类,该类实现Runnable接口,用于处

理主机A接收数据包并显示的操作。具体代码如下:

importjava.net.DatagramPacket;

importjava.net.DatagramSocket;

〃实现Runnable接口,为A主机接收数据

publicclassReceivoForAimplementsRunnable{

publicvoidrun(){//实现run()方法

//初始化数据报套接字和数据报对象

DatagramSocketsocket=null;

DatagramPacketdp=null;

byte[]data=newbyte[8192];〃为接收的数据预分配空间

try{

socket=newDatagramSocket(3000);//创建监听端口3000的数据报套接字

dp=newDatagramPacket(data,data,length);//封装数据

)

catch(Exceptionc){}

while(true){

if(socket==null)break;〃没有接收到数据,结束线程

else

try(

socket.receive(dp);//接收数据报

214

项目八网络编程基础

〃将数据报中的字节数据转换为字符串

Stringmess=newString(dp.getDataO,0,dp.getLengthO);

〃按指定格式输出接收到的信息

System,out.printf(//%40s\n,z,"B对我说:"+mess);

}catch(Exceptione){}

}

)

}

上面的代码使用System.也力.printf()格式化输出接收到数据信息,第一个参数表示

字符串的最小宽度为40,输出后换行。

(3)在项目中添加一个名为UserB的类,用于模拟主机B发送和接收数据报。具体

代码如下:

importjava.net.DatagramPacket;

importjava.net.DatagramSocket;

importjava.net.Inet/\ddress;

importjava.net.SockotKxccption;

importjava.util.Scanner;

publicclassUserB{

publicstaticvoidmain(String口args){

Scannersc=newScanner(System,in);,/仓U建』」描器

ThreadreadData;//声明线程

ReceiveForBreceiver=newReceiveForB();//创建Runnable实现类对象

DatagramSocketsocketB=null;

try{readData=newThread(receiver);〃创建负责接收信息的线程

readData.start();//启动线程

byte[]buf=newbyte[l];〃定义接收数据的字行数组

Stringstr="127.0.0.1”;〃服务器端IP地址

intport=3000;//服务器端的端口号

〃将IP地址封装为InclAddress对象

InetAddrcssaddr=InctAddrcss.gctByName(slr);

try(

socketB=newDatagramSocket();〃创影连接的套接字对象

}catch(SocketExceptione){}

〃创建数据报,发送到地址为辿£的主机的port端口

DatagramPacketdp=newDatagramPacket(buf,buf.length,addr,port);

System.out.print(“我对A说:");

while(sc.hasNext()){//如果输入/内容

Stringinfo=sc.nextLineO;/.获取输入的内容

215

Java开发综合实战

buf=info.gctBytosO;〃将字符串转换为字节数组

if(info,length()==0)

System.;3虽制关闭JVM,退出程序

buf=info.getBytesO;

dp.setData(buf);了将字节数组放入数据报打包

socketB.send(dp);.7发送数据报

Systen.out.print("我继续对A说:”);

}

}catch(Exceptione){〃捕获异常

System.outprintln(e);

}

sc.closeO;

)

}

(4)在项目中添加一个名为ReceiveForB的类,该类实现Runnable接口,用于处

理主机B接收数据包并显示的操作。具体代码如下;

importjava.net.DatagramPacket;

importjava.net.DatagramSocket;

〃实现Runnable接口,为B主机接收数据

publicclassReceiveForBimplementsRunnable{

publicvoidrun(){〃实现run()方法

//初始化数据报套接字和数据报对象

DatagramSockotsocket-null;

DatagramPacketdp=null;

byte[]data=newbyte[8192];〃为接收的数据预分配空间

try{〃创建监听端口9000的数据报套接字

socket=newDatagramSocket(9000);

dp=newDatagramPacket(data,data,length);封装数据

}catch(Excepticne){}

while(true){

if(socket==null)break:/没有接收到数据包,结束线程

else

try(

socket,receive(dp);/,接收数据报

〃将数据报中的字节数据转换为字符串

Stringmess=newString(dp.getData(),0,dp.getLcngth0);

〃按指定格式输出接收到的信息

System.out.printf(/,%40s\n,\'A对我说:"+mcss);

216

项目八网络编程基础

}catch(Exceptione){}

)

)

)

(5)运行程序UserA.java,在控制台中输入信息,按Enter键,发送消息。此时的

控制台如图8—5所示。

日ConsoleX■3C/|邕/|

UserA[JavaApplication]D:\软件\eclipse-java-2021-12-R-win32-x1

welldone!congratulations!

图8—5主机A发送消息

(6)运行程序UserB.java,在控制台中输入信息,如图8—6所示。按Enter键,

即可发送消息。此时自动切换到主机A的消息界面,显示接收到的消息,如图8-7所示。

SConsoleX■X-|七砧届0ConsoleX■»一|国砧[£

UserB(JavaApplication]D:\5XWeclipse-java-2021-12-R-win32-xUserA(JavaApplication]D:^XI+\eclipse-java-2021-12-R-/^n32-x

衣CA法,Thankyou!|发CB泛,uelldone!Congratulations!

kdd厂B於Thankyou!

图8-6主机B输入消息图8—7主机A接收到消息

(7)输入消息,如图8—8所示,按Enter键发送消息。此时自动切换到主机B的

消息界面,显示接收到的消息,如图8—9所示.

SConsoleX■*■|Sc砧>QConsoleX■,—|It&,

UserA(JavaApplication]D:^Xtt^eclipse-java-2021-12-R-win32-xUserBjJavaApplication]D:\K<4\eclipse-java-2021-12-R-win32->

友CB泛,welldone!Congratulations!友HA法,Thankyou!

汇B次;Thankyou!kawtAa,AZ复次,wonderful!

wonderful!

图8—8主机A输入消息图8-9主机B接收到消息

项目总结

217

Java开发综合实战

在上一章的项目实战中已实现了一个简单的单机版进销存管理系统。本章将分离客

户端和服务器端,利用TCPSocket制作一个简易的网络版进销存管理系统。

(1)复制并粘贴“进销存管理系统V7.0”,在CopyProject对话框中修改项目名称

为“进销存管理系统V8.0”,然后单击Copy按钮关闭对话框。

首先设计客户端程序.

(2)在项目中添加一个名为net的包,在包中添加一个名为Client的类,用于实

现客户端主机,并与服务器通信。具体代码如下:

packagenet;

importjava.io.lOExcoption;

importjava.io.Inputstream;

importjava.io.OutputStream;

importjava.net.Socket:

importjava.rmi.UnknownHostException;

publicclassClient{

staticSocketconn\迎接套接字

staticInputStreamin;//输入流

staticOutputStreamout;〃输出流

staticbyte[]buf=nenbyte[20000];

218

项目八网络编程基础

〃静态代码块初始化客户端套接字和10流,只在类第一次加载时执行

static{

try{

〃炉newSoc

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论