网络编程
1、网路的相关概念
(1)网络通信
- 概念:两台设别之间通过网络实现数据传输
- 网络通信:将数据通过网络从一台设备传输到另外一台设备
- java.net包中提供了一系列类或接口,供程序员使用,完成网络通信
(2)网络
- 概念:两台或多台设备通过一定的物理设备连接起来构成了网络
- 根据网络的覆盖范围可以分为:
- 局域网,覆盖范围小,比如一个机房,一个学校内部的局域网
- 城域网,覆盖范围稍微大一些,可以覆盖一个城市
- 广域网,覆盖范围最大,可以覆盖全国,甚至全球
(3)ip地址
- 概念:用于唯一标识网络中的每台计算机/主机
- 查看ip地址命令:
ipconfig
- ip地址的表示形式,点分十进制,每个十进制数的范围为0~255
- ip地址的组成为:网络地址+主机地址
- ip地址分为IPv4和IPv6(128位,16字节),IPv4(32位,4个字节)网络地址资源有限,IPv6解决了网络地址资源数量的问题,也解决了多种接入设备连入互联网的障碍
- ip地址分类:
(4)域名
- 将ip地址根据HTTP协议映射成域名,可以解决ip地址记住比较困难的问题,比如百度的域名为www.baidu.com
- 端口号
- 用于标识计算机上某个特定的网络程序
- 表示形式:整数形式,端口范围0~65535[两个字节表示端口 0~2^16-1]
- 0~1024已经被占用,比如 ssh 22, ftp 21, smtp 25, http 80
- 常用的网络程序端口号:
- tomcat:8080
- mysql:3306
- oracle:1521
- sqlserver:1433
(5)网络通信协议
- 协议(TCP/IP):传输控制协议/因特网互联协议,又叫网络通讯协议,是Internet最基本的协议,Internet国际互联网的基础。简单的说,就是有网络层的IP协议和传输层的TCP协议组成
(6) TCP 和 UDP
-
TCP协议:传输控制协议
- 使用TCP协议前,必须建立TCP连接,形成传输数据通道
- 传输前,采用“三次握手”方式,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
-
UDP协议:用户数据协议
-
将数据、源、目的封装成数据包,不需要建立连接
-
每个数据报的大小限制在64K内,不适合传输大量数据
-
因无需连接,故是不可靠的
-
发送数据结束时无需释放资源(因为不是面向连接的),速度快
-
2、INETADDRESS类
(1)相关方法
- 获取本地InetAddress对象:
getLocalHost
- 根据指定主机名/域名获取ip地址对象:
getByName
- 获取InetAddress对象的主机名
getHostName
- 获取InetAddress对象的地址
getHostAddress
(2)示例
//获取本地InetAddress对象:getLocalHost
InetAddress locolHost = InetAddress.getLocalHost();
System.out.println(locolHost);
//根据指定主机名/域名获取ip地址对象: getByName
InetAddress host2 = InetAddress.getByName("DESKTOP-TNH49H9");
System.out.println(host2);
InetAddress host3 = InetAddress.getByName("www.baidu.com");
System.out.println(host3);
//获取InetAddress对象的主机名 getHostName
String host3AName = host3.getHostName();
System.out.println(host3AName);
//获取InetAddress对象的地址 getHostAddress
String host3Address = host3.getHostAddress();
System.out.println(host3Address);
3、SOCKET
- 套接字(Socket)是两台机器间通信的端点,通信的两端都要有Socket
- 网络通信其实就是Socket间的通信
- Socket允许程序把网络连接当成一个六,数据在两个Socket间通过IO传输
- 一般主动发起通信的应用程序属于客户端,等待通信请求的为服务端
4、TCP网络通信编程
(1)基本介绍
- 基于客户端-服务端的网络通信
- 底层使用的是TCP/IP协议
- 基于Socket的TCP编程
(2)举例
图片服务端和客户端之间的交互,三个文件,一个StreamUtils类,工具类,一个服务端,一个客户端。
服务端负责接收图片并写入图片,从socket中传消息给客户端。
客户端负责读取图片并传送图片,最后从socket接收从服务端传过来的消息。
StreamUtils类:
package JavaEE.chatper16.upload;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @version 1.0
* @auther wangweicheng
* 流的工具包,
*/
public class StreamUtils {
//将输入流转换为bytes
public static byte[] streamToByteArray(InputStream is) throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
byte[] b = new byte[1024];
int len;
while((len=is.read(b))!=-1){
bos.write(b, 0, len);
}
byte[] array = bos.toByteArray();
bos.close();
return array;
}
//将输入流转换为String
public static String streamToString(InputStream is) throws Exception{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder builder= new StringBuilder();
String line;
while((line=reader.readLine())!=null){ //当读取到 null 时,就表示结束
builder.append(line+"\r\n");
}
return builder.toString();
}
}
服务端TCPUploadFileServer:
package JavaEE.chatper16.upload;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @version 1.0
* @auther wangweicheng
*/
public class TCPUploadFileServer {
public static void main(String[] args) throws Exception {
//三个过程
//1、从socket中读取字符文件
//1.1 监听端口,等待连接
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务端等待连接。。。");
Socket socket = serverSocket.accept();
//1.2读取文件
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//2、将字符文件转换为字节流写入到文件当中,转变为图片
byte bytes[] = StreamUtils.streamToByteArray(bis);
String destFilePath = "D:\\成绩单不带说明1.jpg";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
bos.write(bytes);
bos.close();
//3、发消息到客户端图片完成传输,结束
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("收到图片了");
bufferedWriter.flush(); //刷新到socket当中
socket.shutdownOutput(); //设置结束标记
//关闭资源
bufferedWriter.close();
bos.close();
socket.close();
serverSocket.close();
}
}
客户端TCPUploadFileCilent:
package JavaEE.chatper16.upload;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
/**
* @version 1.0
* @auther wangweicheng
*/
public class TCPUploadFileCilent {
public static void main(String[] args) throws Exception {
//三个过程
//1、从文件中读取图片转换为字节流
//1.1建立与服务端的连接
Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
System.out.println("socket:"+socket.getClass());
//1.2从磁盘中读取对应文件,并转换为字节流
String filePath = "D:\\1.jpg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
byte bytes[] = StreamUtils.streamToByteArray(bis);
//2、将字节流写入socket当中
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes); //写入数据通道
bis.close();
socket.shutdownOutput(); //设置结束标记
//3、获取服务端传过来的消息,结束
InputStream inputStream = socket.getInputStream();
String s = StreamUtils.streamToString(inputStream);
System.out.println(s);
//关闭资源
bos.close();
inputStream.close();
socket.close();
}
}
(3)netstat指令
netstat -an
可以查看当前主机网络情况,包括端口监听情况和网络连接情况netstat -an | more
可以分页显示- 要求在dos控制台下执行
win+r
5、UDP网络编程(了解)
(1)基本介绍
- 类DatagramSocket和DatagramPacket【数据包/数据报]实现了基于UDP协议网络程序
- UDP数据报通过套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送达目的地,也不能确定什么时候抵达
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号和接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无需建立发送方与接收方的连接
(2)基本流程
- 核心的两个类/对象 DatagramSocket和DatagramPacket
- 建立发送端、接收端(没有服务端和客户端的概念)
- 调用DatagramSocket的发送、接收方法
- 关闭DatagramSocket
(3)举例
总共分为两个文件,一个接收端UDPReceiveB,一个发送端UDPSenderA
接收端UDPReceiveB:
package JavaEE.chatper16.UDP_;
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
/**
* @version 1.0
* @auther wangweicheng
*/
public class UDPReceiveA {
public static void main(String[] args) throws IOException {
//1、创建DatagramSocket对象,准备在9999端口接收数据
DatagramSocket socket = new DatagramSocket(9999);
//2、接收接收端发回来的信息
byte[] buf = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
//有数据就会接收数据,没有数据就会等待
System.out.println("接收端A等待接受B端数据");
socket.receive(datagramPacket);
System.out.println("接收端A接受到了B端数据的数据");
//进行拆包
int lenth = datagramPacket.getLength();
byte[] data = datagramPacket.getData(); //获取到数据
System.out.println(datagramPacket);
System.out.println(new String(data, 0, lenth));
//3、将需要发送的数据,封装到DatagramPacket对象当中
data = "好的,明天见".getBytes();
//说明参数:需要封装的对象,对象的长度,主机IP,端口号
datagramPacket = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9998);
socket.send(datagramPacket);
//关闭资源
socket.close();
System.out.println("A端退出");
}
}
发送端UDPSenderA:
package JavaEE.chatper16.UDP_;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
/**
* @version 1.0
* @auther wangweicheng
*/
public class UDPSenderB {
public static void main(String[] args) throws IOException {
//1、创建DatagramSocket对象,准备在9998端口发送数据
DatagramSocket socket = new DatagramSocket(9998);
//2、将需要发送的数据,封装到DatagramPacket对象当中
byte[] data = "hello 明天吃火锅~".getBytes();
//说明参数:需要封装的对象,对象的长度,主机IP,端口号
DatagramPacket datagramPacket = new DatagramPacket(data, data.length, InetAddress.getLocalHost(),9999);
socket.send(datagramPacket);
System.out.println("发送端B发送了数据给接收端A");
//3、接收接收端发回来的信息
byte[] buf = new byte[1024];
datagramPacket = new DatagramPacket(buf, buf.length);
//有数据就会接收数据,没有数据就会等待
socket.receive(datagramPacket);
//进行拆包
int lenth = datagramPacket.getLength();
data = datagramPacket.getData(); //获取到数据
System.out.println(datagramPacket);
System.out.println(new String(data, 0, lenth));
//关闭资源
socket.close();
System.out.println("B端退出");
}
}