1、什么是计算机网络
计算机网络是将不同地理位置的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统
2、Java网络编程
Java语言对网络编程提供了良好的支持。通过其提供的接口我们可以很方便地进行网络编程。Java提供了两种常见的网络协议的支持:
- TCP:TCP 是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
- UDP:UDP 是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据包。
3、InetAddress类
- getLocalHost()获得本机主机的一个InetAddress对象,可以通过该对象的到主机的名称和IP地址。
/*
* InetAddress类
* 功能:用于获取本机或指定主机的网络地址
*/
public class Demo01 {
public static void main(String[] args) {
try {
// 获取本机的网络地址(主机名称+IP地址)
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(localHost);
System.out.println("主机名称:" + localHost.getHostName());
System.out.println("IP地址:" + localHost.getHostAddress());
// 获取京东的网络地址(按照主机名称)
InetAddress jdHost = InetAddress.getByName("www.jd.com");
System.out.println("京东主机名称:" + jdHost.getHostName());
System.out.println("京东主机IP:" + jdHost.getHostAddress());
// 获取淘宝的网络地址(按照主机名称获取多个网络地址)
System.out.println("淘宝网所有的网络地址:");
InetAddress[] taobaoHostArray = InetAddress.getAllByName("www.taobao.com");
for(InetAddress taobaoHost :taobaoHostArray) {
System.out.println(taobaoHost.getHostName());
System.out.println(taobaoHost.getHostAddress());
System.out.println("---------------------------------");
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
4、基于TCP/IP的网络编程
4.1 Socket类(套接字)
4.1.1 Socket 概述
这个类实现了客户端套接字(也被称为“套接字”)
该类遵循TCP协议,所以必须与ServerSocket建立连接后,才能进行信息的接送
套接字是两台机器之间的通信的一个端点
它的主要作用就是得到一个客户端的套接字。
4.1.2Socket类相关方法
方法 | 用途 |
---|---|
Socket(InetAddress address, int port) | 构造方法,创建一个流套接字,并将其与指定的IP地址中的指定端口号连接起来。 |
InetAddress-getInetAddress() | 返回套接字连接的地址。 |
InputStream-getInputStream() | 返回此套接字的输入流。 |
OutputStream-getOutputStream() | 返回此套接字的输出流。 |
4.2 ServerSocket类(服务器)
4.2.1 ServerSocket概述
这个类实现了服务器套接字
该类是遵循 TCP协议的,所以,必须要和客户端Socket建立连接,才能完成信息的接送
服务器套接字等待来自网络的请求。
它基于该请求执行某些操作,然后可能向请求者返回结果。
主要是监听目标端口,对客户端对目标端口的行为作出响应。
4.2.1 ServerSocket类相关方法
方法 | 用途 |
---|---|
ServerSocket() | 创建一个绑定服务器套接字 |
InetAddress getInetAddress() | 返回此服务器套接字的本地地址 |
ServerSocket(int port) | 创建一个服务器套接字,绑定到指定的端口 |
Socket-accept() | 监听要对这个套接字作出的连接并接受它 |
下面通过一个例子展示这两个类的使用
示例一:
客户端向服务器发送一个名字说“我是**”,客户端接收服务器消息,并向客户端回答“收到”。
服务器端代码:
/*
* ServerSocket类:服务器端
* Socket类:客户端
* 实现双向通信
*/
public class Demo03 {
public static void main(String[] args) {
// 服务器端
try (ServerSocket serverSocket = new ServerSocket(6001)) {
System.out.println("服务器已启动,正在监听6006端口.......");
// 等待客户端连接
Socket clientSocket = serverSocket.accept();
// 获取客户端的基本信息
System.out.println("客户端" + clientSocket.getInetAddress().getHostAddress() + "发起连接......");
// 获取客户端的输入信息
InputStream in = clientSocket.getInputStream();
byte[] data = new byte[1024];
int length = in.read(data);
//将字节数组转换为字符串
String dataStr = new String(data, 0, length);
System.out.println("客户端说,我是:" + dataStr);
System.out.println();
//服务器端响应(向客户端返回信息 ==》输出信息至客户端)
OutputStream out = clientSocket.getOutputStream();
out.write("收到,over!".getBytes());
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端代码:
public class ClientDemo {
public static void main(String[] args) {
String name = new Scanner(System.in).next();
// 客户端代码
// 需要指定:1.服务器地址;2.服务器端口号
// 创建客户端的Socket(代表连接到指定的服务器端)
try (Socket clientSocket = new Socket("192.168.2.106",6006)){
// 客户端输出信息至服务器(客户端提交数据至服务器)
OutputStream out = clientSocket.getOutputStream();
out.write(("你好,服务器,我是" + name).getBytes());
out.flush();
// 获取服务器反馈的信息
InputStream in = clientSocket.getInputStream();
byte[] data = new byte[1024];
int length = in.read(data);
String dataStr = new String(data,0,length);
System.out.println("服务器说:" + dataStr);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试结果如下:
示例二:
实现一个图片文件的上传功能
图片上传服务器类:
// 图片上传服务器
public class Demo05 {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(8888)){
while (true) {
// 等待客户端连接
Socket clientSocket = serverSocket.accept();
// 启动新线程,处理该客户端的图片上传
Thread thread = new Thread(new UploadImageThread(clientSocket));
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class UploadImageThread implements Runnable {
private Socket clientSocket;
public UploadImageThread(Socket clientSocket) {
this.clientSocket = clientSocket;
}
@Override
public void run() {
//1. 创建上传目录
File uploadFolder = new File("c:/test/测试");
if(!uploadFolder.exists()) {
uploadFolder.mkdirs();
}
//2. 创建新上传的图片文件
//2.1 新上传的图片文件名称
String uploadImageFileName = System.currentTimeMillis()+((int)Math.random()*10000)+".jpg";
BufferedOutputStream bos = null;
try {
//2.2 新上传的图片文件对象
File uploadImageFile = new File(uploadFolder.getAbsolutePath()+ File.separator + uploadImageFileName);
uploadImageFile.createNewFile(); //创建空文件
//2.3 文件输出流
bos = new BufferedOutputStream(new FileOutputStream(uploadImageFile));
//3. 读取上传的图片文件(通过Socket“读取”客户端输出的图片字节信息)
InputStream in = clientSocket.getInputStream();
byte[] data = new byte[1024];
int length = -1;
while((length = in.read(data)) != -1) {
bos.write(data,0,length); //输出保存至服务器的指定上传目录的临时文件中
}
System.out.println("客户端"+clientSocket.getInetAddress().getHostAddress()+"上传了图片!");
//4.向客户端反馈上传结果
OutputStream out = clientSocket.getOutputStream();
out.write("上传成功了哟!".getBytes());
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
bos = null;
}
}
}
}
图片上传客户端类:
public class UploadClientDemo {
public static void main(String[] args) {
String uploadImagePath = "C:\\Users\\apple\\新建文件夹\\1.jpg";
try {
// 创建客户端连接
Socket clientSocket = new Socket("172.0.01",8888);
// 获取输出流(输出至服务器端)
OutputStream out = clientSocket.getOutputStream();
// 读取上传的图片文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(uploadImagePath));
byte[] data = new byte[1024];
int length = -1;
while((length = bis.read(data)) != -1) {
out.write(data); //通过Socket的输出流,输出至服务器端
}
// 向服务器端输出一个结束符号
clientSocket.shutdownOutput();
// 获取服务器端返回的上传状态
InputStream in = clientSocket.getInputStream();
data = new byte[1024];
length = in.read(data);
String status = new String(data,0,length);
System.out.println(status);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注: 以上测试案例在一台电脑完成需要开启两个开发工具,一个运行客户端代码,一个运行服务器代码。
网络编程的URL和UDP将在下一篇文章做简单介绍。