第10章 网络编程教学设计.docx
《第10章 网络编程教学设计.docx》由会员分享,可在线阅读,更多相关《第10章 网络编程教学设计.docx(21页珍藏版)》请在冰豆网上搜索。
第10章网络编程教学设计
传智播客
《Java基础入门》
教学设计
课程名称:
Java基础教程
授课年级:
2014年级
授课学期:
2014学年第一学期
教师姓名:
某某老师
2014年05月14日
课题名称
第10章网络编程
计划学时
4课时
内容分析
网络编程是指在计算机上编写一些实现网络连接的程序,这些程序可以实现同一网络中的计算机之间的通信。
本章将针对网络编程的相关知识进行详细地讲解,并结合程序学习如何使用Java编写网络程序。
教学目标及基本要求
通过对本章的学习,要求学生了解网络通信协议,TCP/IP协议的特点、熟悉IP地址和端口号的作用、InetAddress对象的使用、掌握UDP和TCP通信方式、ServerSocket、Socket、DatagramPacket、DatagramSocket类的使用。
重点及措施
教学重点:
TCP/IP协议、UDP和TCP通信、ServerSocket、Socket、DatagramPacket、DatagramSocket类的使用方法。
难点及措施
教学难点:
TCP/IP协议、UDP和TCP通信、ServerSocket、Socket、DatagramPacket、DatagramSocket类的使用方法。
教学方式
教学采用教师课堂讲授为主,使用教学PPT讲解
教
学
过
程
第一课时
(网络通信协议、IP地址和端口号、InetAddress、UDP与TCP协议)
网络通信协议
在计算机网络中,实现计算机连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。
网络通信协议有很多种,目前应用最广泛的是TCP/IP协议,它是一个包括TCP协议和IP协议,UDP协议、ICMP协议和其它一些协议的协议组。
在学习具体协议之前首先了解一下TCP/IP协议组的层次结构。
TCP/IP协议的层次结构比较简单,共分为四层:
应用层、传输层、网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解。
●链路层:
链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、双绞线提供的驱动。
●网络层:
网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。
●运输层:
主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。
●应用层:
主要负责应用程序的协议,例如HTTP协议、FTP协议等。
IP地址和端口号
在TCP/IP协议中,通过IP地址来指定接受数据的计算机或者发送数据的计算机,通过端口号来区分不同的应用程序。
接下来通过一个图例来描述IP地址和端口号的作用,如图所示。
网络中一台计算机可以通过IP地址去访问另一台计算机,并通过端口号访问目标计算机中的某个应用程序。
InetAddress
JDK中提供了一个InetAdderss类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法,下表列举了InetAddress类的一些常用方法。
方法声明
功能描述
InetAddressgetByName(Stringhost)
参数host表示指定的主机,该方法用于在给定主机名的情况下确定主机的IP地址
InetAddressgetLocalHost()
创建一个表示本地主机的InetAddress对象
StringgetHostName()
得到IP地址的主机名,如果是本机则是计算机名,不是本机则是主机名,如果没有域名则是IP地址
booleanisReachable(inttimeout)
判断指定的时间内地址是否可以到达
StringgetHostAddress()
得到字符串格式的原始IP地址
UDP与TCP协议
在TCP/IP结构图中,提到传输层的两个重要的高级协议,分别是UDP和TCP,其中UDP是UserDatagramProtocol的简称,称为用户数据报协议,TCP是TransmissionControlProtocol的简称,称为传输控制协议。
第二课时
(UDP通信、DatagramPacket、DatagramSocket、UDP网络程序、UDP案例)
UDP通信
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。
在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
UDP的交换过程如下图所示:
DatagramPacket
DatagramPacket类是UDP通信中用于封装发送或者接受数据的“集装箱”。
它的构造方法如下所示:
●DatagramPacket(byte[]buf,intlength);
●DatagramPacket(byte[]buf,intlength,InetAddressaddr,intport):
●DatagramPacket(byte[]buf,intoffset,intlength):
●DatagramPacket(byte[]buf,intoffset,intlength,InetAddressaddr,intport):
DatagramPacket类的常用方法:
方法声明
功能描述
InetAddressgetAddress()
该方法用于返回发送端或者接收端的IP地址
intgetPort()
该方法用于返回发送端或者接收端的端口号
byte[]getData()
该方法用于返回将要接收或者将要发送的数据
intgetLength()
该方法用于返回接收或者将要发送数据的长度
DatagramSocket
在UDP通信中,DatagramSocket的实例对象可以用来发送和接受DatagramPacket数据包,发送数据的过程如下图所示。
DatagramSocket的构造方法如下所示:
●DatagramSocket():
●DatagramSocket(intport):
●DatagramSocket(intport,InetAddressaddr):
DatagramSocket的常用方法如下表所示:
方法声明
功能描述
voidreceive(DatagramPacketp)
该方法用于将接收到的数据填充到DatagramPacket数据包中
voidsend(DatagramPacketp)
该方法用于发送DatagramPacket数据包
voidclose()
关闭当前Socket,通知驱动程序释放资源
UDP网络程序
要实现UDP通信需要创建一个接收端程序和一个发送端程序,因此我们需要编写两个程序。
(1)接收端程序
publicclassExample02{
publicstaticvoidmain(String[]args)throwsException{
//创建一个长度为1024的字节数组,用于接收数据
byte[]buf=newbyte[1024];
//定义一个DatagramSocket对象,监听的端口号为8954
DatagramSocketds=newDatagramSocket(8954);
//定义一个DatagramPacket对象,用于接收数据
DatagramPacketdp=newDatagramPacket(buf,1024);
System.out.println("等待接收数据");
//等待接收数据,如果没有数据则会阻塞
ds.receive(dp);
/*
*调用DatagramPacket的方法获得接收到的信息,
*包括数据的内容、长度、发送的IP地址和端口号
*/
Stringstr=newString(dp.getData(),0,dp.getLength())
+"from"+dp.getAddress().getHostAddress()
+":
"+dp.getPort();
System.out.println(str);//打印接收到的信息
ds.close();//释放资源
}
}
程序运行结果如图所示。
(2)发送端程序
publicclassExample03{
publicstaticvoidmain(String[]args)throwsException{
//创建一个DatagramSocket对象
DatagramSocketds=newDatagramSocket(3000);
Stringstr="helloworld";//要发送的数据
/*
*创建一个要发送的数据包,数据包包括发送的数据,数据的长度,
*接收端的IP地址以及端口号
*/
DatagramPacketdp=newDatagramPacket(str.getBytes(),
str.length(),InetAddress.getByName("localhost"),8954);
System.out.println("发送信息");
ds.send(dp);//发送数据
ds.close();//释放资源
}
}
运行结果如图所示。
并且接收端程序中的控制台内容发生变化,变化结果如下图所示。
注意:
在创建发送端的DatagramSocket对象时,可以不指定端口号,指定端口号目的是为了每次运行时接收端的getPort()方法返回值都是一致的,否则发送端的端口号由系统自动分配,接收端的getPort()方法的返回值每次都不同。
UDP案例——聊天程序
✧功能需求
UDP聊天程序主要是想通过监听指定的端口号,目标IP地址和目标端口号,实现消息的发送和接收功能,并把聊天内容显示出来。
✧所用到的技术
1、UDP通信中的DatagramSocket、DatagramPacket类的相关方法。
2、在服务器监听方法中开启了新线程,把接受消息的实现方法全部放到新线程的run()方法中。
3、使用Swing技术设计简单的对话框界面。
✧功能模块
1、界面实现
对于界面的实现,需要提供显示聊天记录的区域、聊天输入框等区域。
2、编写事件处理器(发送信息)
界面开发完成后,为界面上的按钮添加监听事件。
●在发送消息前,判断IP地址和端口号是否为空。
●把输入文本内容显示在指定区域的功能。
●添加清空文本显示区域内容的功能
3、DatagramSocket的启动监听(接受消息)
在程序中实现两个功能:
●接受用户填写程序监听的端口号
●使用多线程技术接受消息。
4、功能测试
开启两个聊天程序,分别填写对方的IP地址和监听端口号,测试聊天功能。
第三课时
(TCP通信、ServerSocket、Socket、TCP网络程序、多线程TCP网络程序、TCP案例)
TCP通信
TCP协议是面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输。
整个交互过程如图所示。
由于TCP协议的面向连接特性,它可以保证传输数据的安全性,所以是一个被广泛采用的协议。
ServerSocket
在TCP程序中,ServerSocket表示服务器端,该对象相当于开启一个服务,并等待客户端的连接。
ServerSocket的构造方法如下所示:
●ServerSocket():
●ServerSocket(intport):
●ServerSocket(intport,intbacklog):
●ServerSocket(intport,intbacklog,InetAddressbindAddr):
ServerSocket的常用方法如下表所示:
方法声明
功能描述
Socketaccept()
该方法用于等待客户端的连接,在客户端连接之前一直处于阻塞状态,如果有客户端连接就会返回一个与之对应的Socket对象
InetAddressgetInetAddress()
该方法用于返回一个InetAddress对象,该对象中封装了ServerSocket绑定的IP地址
booleanisClosed()
该方法用于判断ServerSocket对象是否为关闭状态,如果是关闭状态则返回true,反之则返回false
voidbind(SocketAddress
endpoint)
该方法用于将ServerSocket对象绑定到指定的IP地址和端口号,其中参数endpoint封装了IP地址和端口号
Socket
在TCP程序中,除了服务器端程序运行以外,还需要客户端程序与之交互,为此JDK提供了一个Socket类,用于实现TCP客户端程序。
Socket的构造方法有三种,具体如下:
●Socket()
●Socket(Stringhost,intport)
●Socket(InetAddressaddress,intport)
Socket的常用方法如下表所示:
方法声明
功能描述
intgetPort()
该方法返回Socket对象与服务器端连接的端口号
InetAddressgetLocalAddress()
该方法用于获取Socket对象绑定的本地IP地址,并将IP地址封装成InetAddress类型的对象返回
voidclose()
该方法用于关闭Socket连接,结束本次通信
InputStreamgetInputStream()
该方法返回一个InputStream类型的输入流对象
OutputStreamgetOutputStream()
该方法返回一个OutputStream类型的输出流对象
当客户端和服务端建立连接后,数据是以IO流的形式进行交互的,从而实现通信。
接下来通过一张图来描述服务器端和客户端的数据传输,如下图所示。
TCP网络程序
要实现TCP通信需要创建一个服务器端程序和一个客户端程序,因此我们需要编写两个程序。
(1)服务器端程序
publicclassExample04{
publicstaticvoidmain(String[]args)throwsException{
//创建TCPServer对象,并调用listen()方法
newTCPServer().listen();
}
}
//TCP服务端
classTCPServer{
privatestaticfinalintPORT=7788;//定义一个端口号
//定义一个listen()方法,抛出一个异常
publicvoidlisten()throwsException{
//创建ServerSocket对象
ServerSocketserverSocket=newServerSocket(PORT);
//调用ServerSocket的accept()方法接收数据
Socketclient=serverSocket.accept();
//获取客户端的输出流
OutputStreamos=client.getOutputStream();
System.out.println("开始与客户端交互数据");
//当客户端连接到服务端时,向客户端输出数据
os.write(("传智播客欢迎你!
").getBytes());
//模拟执行其它功能占用的时间
Thread.sleep(5000);
System.out.println("结束与客户端交互数据");
os.close();
client.close();
}
}
运行结果如下图所示。
(2)客户端程序
publicclassExample05{
publicstaticvoidmain(String[]args)throwsException{
//创建TCPClient对象,并调用connect()方法
newTCPClient().connect();
}
}
//TCP客户端
classTCPClient{
//服务端的端口号
privatestaticfinalintPORT=7788;
publicvoidconnect()throwsException{
//创建一个Socket并连接到给出地址和端口号的计算机
Socketclient=newSocket(InetAddress.getLocalHost(),PORT);
//得到接收数据的流
InputStreamis=client.getInputStream();
//定义1024个字节数组的缓冲区
byte[]buf=newbyte[1024];
//将数据读到缓冲区中
intlen=is.read(buf);
//将缓冲区中的数据输出
System.out.println(newString(buf,0,len));
//关闭Socket对象,释放资源
client.close();
}
}
运行结果如下图所示。
当客户端访问服务端程序时,服务器接收到数据后会解除阻塞状态,把服务器里剩下的功能代码实现,服务器控制台会发生变化,变化结果如下图所示。
多线程的TCP网络程序
在实际开发中,很多服务器端程序都是允许被多个应用程序访问的,例如门户网站可以被多个用户问,因此服务器都是多线程的。
(1)实现多线程功能的服务器端
classTCPServer{
//定义一个静态常量作为端口号
privatestaticfinalintPORT=7788;
publicvoidlisten()throwsException{
//创建ServerSocket对象,监听指定的端口
ServerSocketserverSocket=newServerSocket(PORT);
//使用while循环不停的接收客户端发送的请求
while(true){
//调用ServerSocket的accept()方法与客户端建立连接
finalSocketclient=serverSocket.accept();
//下面的代码用来开启一个新的线程
newThread(){
publicvoidrun(){
OutputStreamos;//定义一个输出流对象
try{
//获取客户端的输出流
os=client.getOutputStream();System.out.println("开始与客户端交互数据");
os.write(("传智播客欢迎你!
").getBytes());
//使线程休眠5000毫秒
Thread.sleep(5000);
System.out.println("结束与客户端交互数据");
os.close();//关闭输出流
client.close();//关闭Socket对象
}catch(Exceptione){
e.printStackTrace();
}
};
}.start();
}
}
}
此时,再次开启服务端程序,运行三个客户端程序的运行结果如下图所示。
TCP案例——文件上传
目前大多数服务器都会提供文件上传的功能,由于文件上传需要数据的安全性和完整性,所以需要使用TCP协议来实现。
接下来通过一个案例来实现图片上传的功能,首先编写服务器端程序,用来接收图片,如例程所示。
publicclassExample07{
publicstaticvoidmain(String[]args)throwsException{
//创建ServerSocket对象
ServerSocketserverSocket=newServerSocket(10001);
while(true){
//调用accept()方法接收客户端请求,得到Socket对象
Sockets=serverSocket.accept();
//每当和客户端建立Socket连接后,单独开启一个线程处理和客户端的交互
newThread(newServerThread(s)).start();
}
}
}
classServerThreadimplementsRunnable{
//持有一个Socket类型的属性
privateSocketsocket;
//构造方法中把Socket对象作为实参传入
publicServerThread(Socketsocket){
this.socket=socket;
}
publicvoidrun(){
//获取客户端的IP地址
Stringip=socket.getInetAddress().getHostAddress();
//上传图片个数
intcount=1;
try{
InputStreamin=socket.getInputStream();
//创建上传图片目录的File对象
FileparentFile=newFile("d:
\\upload\\");
//如果不存在,就创建这个目录
if(!
parentFile.exists()){
parentFile.mkdir();
}
//把客户端的IP地址作为上传文件的文件名
Filefile=newFile(parentFile,ip+"("+count+").jpg");
while(file.exists()){
//如果文件名存在,则把count++
file=newFile(parentFile,ip+"("+(count++)+").jpg")