Java作业六 网络通信
1. 什么是TCP/IP协议?它有什么特点?
答:
(1)什么是TCP/IP协议
TCP/IP传输协议,即传输控制/网络协议,也叫作网络通讯协议。它是在网络的使用中的最基本的通信协议。TCP/IP传输协议对互联网中各部分进行通信的标准和方法进行了规定。并且,TCP/IP传输协议是保证网络数据信息及时、完整传输的两个重要的协议。TCP/IP传输协议是严格来说是一个四层的体系结构,应用层、传输层、网络层和数据链路层都包含其中,其中应用层的主要协议有Telnet、FTP、SMTP等,是用来接收来自传输层的数据或者按不同应用要求与方式将数据传输至传输层;传输层的主要协议有UDP、TCP,是使用者使用平台和计算机信息网内部数据结合的通道,可以实现数据传输与数据共享;网络层的主要协议有ICMP、IP、IGMP,主要负责网络中数据包的传送等;而网络访问层,也叫网路接口层或数据链路层,主要协议有ARP、RARP,主要功能是提供链路管理错误检测、对不同通信媒介有关信息细节问题进行有效处理等。
(2)TCP/IP协议特点
协议标准是完全开放的,并且独立于特定的计算机硬件与操作系统;
独立于网络硬件系统,可以运行在广域网,更适合于互联网;
网络地址统一分配,网络中每一设备和终端都具有一个唯一地址;
高层协议标准化,可以提供多种多样可靠网络服务。
2.简述URL与Socket通信的区别。
答:
(1)区别
Socket:
利用socket进行通信时,在服务器端运行一个socket通信程序。服务器端不停地监听某个端口,等待客户的连接申请,接到申请后建立连接并进行通信,所以,在socket通信方式中,服务器是主动等待连接通信的到来。
利用socket进行通信时,服务器端的程序可以打开多个线程与多个客户进行通信,还可以通过服务器使各个客户之间进行通信。这种方式比较灵活,适用于一些较复杂的通信,但是服务器端的程序必须始终处于运行状态以监听端口。
URL:
利用URL进行通信时,在服务器端常驻一个CGI程序,但它一直处于休眠状态。只有在客户端要求建立连接时才被激活,然后与用户进行通信。所以,在URL 通信方式中,服务器是被动等待连接通信的到来。
利用 URL进行通信时,服务器端的程序只能与一个客户进行通信,形式比较单一。但是它不需要服务器端的CGI程序一直处于运行状态,只是在有客户申请时才被激活。所以,这种方式比较适用于客户机的浏览器与服务器之间的通信。
3.简述Socket通信机制,说明客户端如何与服务器进行连接。
答:
(1)通信机制
Server端创建ServerSocket对象,监听某端口;Client端创建Socket对象,向Server的监听服务发送连接请求;
Server端接受Client端的请求,用accept()返回的Socket建立连接,此时连接建立。Server端和Client端分别通过向Socket读写数据完成与对方的通信,这称作数据通信。最后是拆分连接,Client端关闭Socket,结束Server端的通信,Server端关闭Socket,结束与当前Client的通信,等待其它请求。如果没有其他请求,Server端关闭ServerSocket对象,结束监听服务。
(2)客户端和服务器连接
服务器端生成一个ServerSocket实例对象,随时监听客户端的连接请求;客户端生成一个Socket实例对象,并发出连接请求;服务器端通过accept()方法接收到客户端的请求后,开辟一个接口与之进行连接,并生成所需的I/O数据流;通信都是通过一对InputStream()和OutputStream()进行的,通信结束后,两端分别关闭对应的Socket接口。
4.说明并尝试通过URL从服务器上读取一个文本文件,并显示该文本文件的内容。
import java
.net
.*
;
import java
.io
.*
;
public class HomeWork6_4
{
public static void main(String args
[]) throws Exception
{
URL myurl
= new URL("https://mirrors6.tuna.tsinghua.edu.cn/ubuntu-releases/robots.txt");
URLConnection uc
= myurl
.openConnection();
InputStreamReader isr
= new InputStreamReader(uc
.getInputStream());
BufferedReader in
= new BufferedReader(isr
);
String inputLine
;
while ((inputLine
= in
.readLine()) != null
)
{
System
.out
.println(inputLine
);
}
in
.close();
}
}
5.编写程序,用Socket通信机制在服务器和客户端之间传输文件。
服务器端
import java
.io
.DataInputStream
;
import java
.io
.File
;
import java
.io
.FileOutputStream
;
import java
.math
.RoundingMode
;
import java
.net
.ServerSocket
;
import java
.net
.Socket
;
import java
.text
.DecimalFormat
;
public class HomeWork6_5Server extends ServerSocket
{
private static final int SERVER_PORT
= 8888;
private static DecimalFormat df
= null
;
static
{
df
= new DecimalFormat("#0.0");
df
.setRoundingMode(RoundingMode
.HALF_UP
);
df
.setMinimumFractionDigits(1);
df
.setMaximumFractionDigits(1);
}
public HomeWork6_5Server() throws Exception
{
super(SERVER_PORT
);
}
public void load() throws Exception
{
while (true)
{
Socket socket
= this.accept();
new Thread(new Task(socket
)).start();
}
}
class Task implements Runnable
{
private Socket socket
;
private DataInputStream dis
;
private FileOutputStream fos
;
public Task(Socket socket
)
{
this.socket
= socket
;
}
@Override
public void run()
{
try {
dis
= new DataInputStream(socket
.getInputStream());
String fileName
= dis
.readUTF();
long fileLength
= dis
.readLong();
File directory
= new File("D:\\FTCache");
if(!directory
.exists()) {
directory
.mkdir();
}
File file
= new File(directory
.getAbsolutePath() + File
.separatorChar
+ fileName
);
fos
= new FileOutputStream(file
);
byte[] bytes
= new byte[1024];
int length
= 0;
while((length
= dis
.read(bytes
, 0, bytes
.length
)) != -1) {
fos
.write(bytes
, 0, length
);
fos
.flush();
}
System
.out
.println("======== 文件接收成功 [File Name:" + fileName
+ "] [Size:" + getFormatFileSize(fileLength
) + "] ========");
} catch (Exception e
) {
e
.printStackTrace();
} finally {
try {
if(fos
!= null
)
fos
.close();
if(dis
!= null
)
dis
.close();
socket
.close();
} catch (Exception e
) {}
}
}
}
private String
getFormatFileSize(long length
) {
double size
= ((double) length
) / (1 << 30);
if(size
>= 1) {
return df
.format(size
) + "GB";
}
size
= ((double) length
) / (1 << 20);
if(size
>= 1) {
return df
.format(size
) + "MB";
}
size
= ((double) length
) / (1 << 10);
if(size
>= 1) {
return df
.format(size
) + "KB";
}
return length
+ "B";
}
public static void main(String
[] args
) {
try {
HomeWork6_5Server server
= new HomeWork6_5Server();
server
.load();
} catch (Exception e
) {
e
.printStackTrace();
}
}
}
客户端
import java
.io
.DataOutputStream
;
import java
.io
.File
;
import java
.io
.FileInputStream
;
import java
.net
.Socket
;
import com
.sun
.tools
.javac
.Main
;
public class HomeWork6_5Client extends Socket
{
private static final String SERVER_IP
= "127.0.0.1";
private static final int SERVER_PORT
= 8888;
private Socket client
;
private FileInputStream fis
;
private DataOutputStream dos
;
public HomeWork6_5Client() throws Exception
{
super(SERVER_IP
, SERVER_PORT
);
this.client
= this;
System
.out
.println("Cliect[port:" + client
.getLocalPort() + "] 成功连接服务端");
}
public void sendFile() throws Exception
{
try
{
File file
= new File("C:\\test.txt");
if(file
.exists()) {
fis
= new FileInputStream(file
);
dos
= new DataOutputStream(client
.getOutputStream());
dos
.writeUTF(file
.getName());
dos
.flush();
dos
.writeLong(file
.length());
dos
.flush();
System
.out
.println("======== 开始传输文件 ========");
byte[] bytes
= new byte[1024];
int length
= 0;
long progress
= 0;
while((length
= fis
.read(bytes
, 0, bytes
.length
)) != -1)
{
dos
.write(bytes
, 0, length
);
dos
.flush();
progress
+= length
;
System
.out
.print("| " + (100*progress
/file
.length()) + "% |");
}
System
.out
.println();
System
.out
.println("======== 文件传输成功 ========");
}
}
catch (Exception e
)
{
e
.printStackTrace();
}
finally
{
if(fis
!= null
)
fis
.close();
if(dos
!= null
)
dos
.close();
client
.close();
}
}
public static void main(String
[] args
)
{
try
{
HomeWork6_5Client client
= new HomeWork6_5Client();
client
.sendFile();
}
catch (Exception e
)
{
e
.printStackTrace();
}
}
}