回顾总结17
网络
java.net包下提供了一系列的类或接口,供程序员使用,完成网络通信
IP
标识网络上设备的身份
域名
是为了方便记忆,解决记ip的困难
比如www.baidu.com,它的ip地址是110.242.68.3
相当于www.baidu.com引用了ip地址,
端口号
用于标识计算机上某个特定的网络程序
使用两个字节表示,范围有0 - 65535;其中0-1024被固定网络程序占用了
常见网络程序端口号
- tomcat:8080
- mysql:3306
- oracle:1521
- sqlserver:1433
网络通信协议
协议就是数据的组织形式(封装)
TCP/IP协议
Transmission Control Protocol:传输控制协议
Internet Protocol:因特网互联协议
tcp/ip:网络通讯协议
OSI模型
原本是七层,但是太细了,现在用的是四层
| OSI模型 | TCP/IP模型 | 对应协议 |
|---|---|---|
| 应用层 | ||
| 表示层 | 应用层 | HTTP、DNS、telnet、ftp... |
| 会话层 | ||
| 传输层 | 传输层(TCP) | TCP、UDP... |
| 网络层 | 网络层(IP) | IP、ICMP、ARP... |
| 数据链路层 | ||
| 物理层 | 物理+数据链路层 | Link |

TCP协议
传输控制协议
- 使用TCP协议前,需要建立TCP连接,形成传输数据通道
- 传输前,采用"三次握手"方式,并且是可靠传输
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输(可靠性)
- 传输后,采用"四次挥手"方式,可靠传输
- 传输完毕,需要释放已建立的连接。效率低,TCP连接同时只能连接一个
UDP协议
用户数据协议
- 将数据、源地址、目的地址封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内,不适合传输大量数据
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源(因为不需要连接)速度快
InetAddress类
获取本机信息(主机名和ip)
通过域名获取远程服务器的ip
常用方法
- getLocalHost:获取本机InetAddress对象,会返回主机名(本机名称)和ip地址
- getByName:根据指定主机名/域名获取ip地址对象
- getHostName:获取InetAddress对象的主机名
- getHostAddress:获取InetAddress对象的地址
TCP网络通信编程
是端口对端口之间的网络通信
服务器端是可以指定的
客户端是TCP协议随机分配的
字节传输单向
服务器端
public class ServeSocket_ {
public static void main(String[] args) throws IOException {
//声明一个byte数组用来读取传送过来的数据
byte[] bytes = new byte[1024];
//定义一个int型数据,记录数组长度
int len = 0;
//服务器端,new一个ServerSocket,监听9999端口
ServerSocket serverSocket = new ServerSocket(9999);
//ServerSocket等待客户端消息,创建Socket
Socket socket = serverSocket.accept();
//使用输入流接收客户端信息
InputStream inputStream = socket.getInputStream();
//如果输入流里面还有数据就读取
while ((len = inputStream.read(bytes)) != -1){
//读取bytes数组里的数据,从0到len位置的
System.out.println(new String(bytes,0,len));
}
//关闭流和socket,还有ServerSocket
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端
public class ClientSocket_ {
public static void main(String[] args) throws IOException {
//new一个Socket,需要连接的ip地址,和端口号
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//连接上了之后,获取输出流
OutputStream outputStream = socket.getOutputStream();
//用输出流写入数据
outputStream.write("hello,java".getBytes(StandardCharsets.UTF_8));
//关闭流,关闭socket
outputStream.close();
socket.close();
}
}
字节传输双向
服务器端
public class Socket_2Server {
public static void main(String[] args) throws IOException {
//声明一个byte数组用来读取传送过来的数据
byte[] bytes = new byte[1024];
//定义一个int型数据,记录数组长度
int len = 0;
//服务器端,new一个ServerSocket,监听9999端口
ServerSocket serverSocket = new ServerSocket(9999);
//ServerSocket等待客户端消息,创建Socket
Socket socket = serverSocket.accept();
//使用输入流接收客户端信息
InputStream inputStream = socket.getInputStream();
//如果输入流里面还有数据就读取
while ((len = inputStream.read(bytes)) != -1){
//读取bytes数组里的数据,从0到len位置的
System.out.println(new String(bytes,0,len));
}
//读取完之后,获取输出流
OutputStream outputStream = socket.getOutputStream();
//写入数据
outputStream.write("hello,client".getBytes());
//写完了,记得通知对面停止流的使用
socket.shutdownOutput();
//关闭流和socket,还有ServerSocket
outputStream.close();
inputStream.close();
socket.close();
serverSocket.close();
}
}
客户端
public class Socket_2Client {
public static void main(String[] args) throws IOException {
//new一个Socket,需要连接的ip地址,和端口号
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//连接上了之后,获取输出流
OutputStream outputStream = socket.getOutputStream();
//用输出流写入数据
outputStream.write("hello,server".getBytes());
//写完之后,通知对面停止输出流的使用
socket.shutdownOutput();
//获取输入流
InputStream inputStream = socket.getInputStream();
int len = 0;
byte[] bytes = new byte[1024];
//读取数据
while ((len = inputStream.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}
//关闭流,关闭socket
inputStream.close();
outputStream.close();
socket.close();
}
}
字符传输双向
服务器端
public class Socket_3Server {
public static void main(String[] args) throws IOException {
//声明一个字符串用来接收每行的数据
String str = "";
//服务器端,new一个ServerSocket,监听9999端口
ServerSocket serverSocket = new ServerSocket(9999);
//ServerSocket等待客户端消息,创建Socket
Socket socket = serverSocket.accept();
//使用输入流接收客户端信息
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//读取一行数据
str = bufferedReader.readLine();
System.out.println(str);
//读取完之后,获取输出流
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
//写入数据
bufferedWriter.write("hello,client");
//写完了,使用newLine作为改行的结束符,通知对面该行结束,然后把数据刷进去
bufferedWriter.newLine();
bufferedWriter.flush();
//关闭流和socket,还有ServerSocket
bufferedWriter.close();
bufferedReader.close();
socket.close();
serverSocket.close();
}
}
客户端
public class Socket_3Client {
public static void main(String[] args) throws IOException {
//new一个Socket,需要连接的ip地址,和端口号
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//连接上了之后,获取输出流
OutputStream outputStream = socket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
//用输出流写入数据
bufferedWriter.write("hello,server");
//写完之后,使用newLine结束该行,通知对面,然后把数据刷过去
bufferedWriter.newLine();//字符流结束使用newLine时,输入流需要使用readLine
bufferedWriter.flush();
//获取输入流
InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = "";
//读取数据
str = bufferedReader.readLine();
System.out.println(str);
//关闭流,关闭socket
bufferedReader.close();
bufferedWriter.close();
socket.close();
}
}
传输文件双向
服务器端
/**
* 这是服务器端
* 1.新建ServerSocket服务
* 2.等待连接,新建Socket
* 3.等待客户端传送图片
* 4.保存到本机
* 5.完成后,给客户端传送“收到图片”信息
*/
public class Server {
public static void main(String[] args) throws IOException {
//1.新建ServerSocket服务
ServerSocket serverSocket = new ServerSocket(9999);
//2.等待连接,新建Socket
Socket socket = serverSocket.accept();
//3.等待客户端传送图片
BufferedInputStream bufferedInputStream = new BufferedInputStream(socket.getInputStream());
//4.保存到本机
String dest = "e:\\dva.jpg";
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest,true));
byte[] bytes = new byte[1024];
while((bufferedInputStream.read(bytes)) != -1){
bufferedOutputStream.write(bytes);
bufferedOutputStream.flush();
}
//5.完成后,给客户端传送“收到图片”信息
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferedWriter.write("收到图片,OVER");
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
bufferedOutputStream.close();
bufferedInputStream.close();
socket.close();
serverSocket.close();
}
}
客户端
/**
* 这是客户端
* 1.连接服务器端
* 2.从自己电脑上获取图片到程序里
* 3.把图片,从该程序传输给服务器端
* 4.等待服务器端传输“获取图片”信息
* 5.把“获取图片”信息打印出来
*/
public class Client {
public static void main(String[] args) throws IOException {
//1.连接服务器端
Socket socket = new Socket(InetAddress.getLocalHost(),9999);
//2.从自己电脑上获取图片到程序里
String src = "d:\\dva.jpg";
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
//3.把图片,从该程序传输给服务器端
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
int len;
byte[] bytes = new byte[1024];
while ((len = bufferedInputStream.read(bytes)) != -1){
bufferedOutputStream.write(bytes,0,len);
bufferedOutputStream.flush();
}
socket.shutdownOutput();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String str;
while ((str = (bufferedReader.readLine())) != null){
System.out.print(str);
}
bufferedReader.close();
bufferedOutputStream.close();
bufferedInputStream.close();
socket.close();
}
}
netstat指令
netstat:可以查看TCP网络连接的情况和端口监听情况
netstat -an:可以查看TCP和UDP网络连接情况和端口监听情况
netstat - an | more:可以分页显示上述情况
netstat -anb:可以查看具体那个程序(需要管理员权限)
details
- Listening表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息
- 可以输入ctrl + c 退出当前netstat指令
UDP网络通信编程
- 类DatagramSocket和DatagramPacket[数据包/数据报]实现了基于UDP协议的网络程序
- UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
- DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号,以及接收端的IP地址和端口号
- UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
通信流程
- 核心的两个类/对象DatagramSocket和DatagramPacket
- 建立发送端,接收端
- 发送数据前,建立数据包DatagramPacket对象
- 调用DatagramSocket的发送,接收方法
- 关闭DatagramSocket
通信单向
发送端
public class UDP_1Sender {
public static void main(String[] args) throws IOException {
//新建一个DatagramSocket数据包,准备在8888端口接收数据
DatagramSocket socket = new DatagramSocket(8888);
//将需要发送的数据,装包
byte[] data = "hello,明天学Java~".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.43.100"),9999);
socket.send(packet);
socket.close();
}
}
接收端
public class UDP_1Receiver {
public static void main(String[] args) throws IOException {
//创建一个DatagramSocket
DatagramSocket socket = new DatagramSocket(9999);
//UDP协议,一个数据包最大是64K
byte[] bytes = new byte[1024];
//创建一个DatagramPacket对象,准备接收数据
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//调用接收方法,将通过网络传输的DatagramPacket对象接收下来
socket.receive(packet);
//获取到数据包,把packet进行拆包,取出数据并显示
int length = packet.getLength();//获取数据长度
byte[] data = packet.getData();
System.out.println(new String(data,0,length));
//关闭资源
socket.close();
}
}
通信双向
先发送端
public class UDP_2Sender {
public static void main(String[] args) throws IOException {
//新建一个DatagramSocket数据包,准备在8888端口接收数据
DatagramSocket socket = new DatagramSocket(8888);
//将需要发送的数据,装包
byte[] data = "hello,明天学Java~".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.43.100"),9999);
socket.send(packet);
//准备接收,获取一个包
byte[] bytes = new byte[1024];
//直接重新赋值,不声明新的变量了
packet = new DatagramPacket(bytes,bytes.length);
socket.receive(packet);
data = packet.getData();
int length = packet.getLength();
System.out.println(new String(data,0,length));
socket.close();
}
}
先接收端
public class UDP_2Receiver {
public static void main(String[] args) throws IOException {
//创建一个DatagramSocket
DatagramSocket socket = new DatagramSocket(9999);
//UDP协议,一个数据包最大是64K
byte[] bytes = new byte[1024];
//创建一个DatagramPacket对象,准备接收数据
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
//调用接收方法,将通过网络传输的DatagramPacket对象接收下来
socket.receive(packet);
//获取到数据包,把packet进行拆包,取出数据并显示
int length = packet.getLength();//获取数据长度
byte[] data = packet.getData();
System.out.println(new String(data,0,length));
//获取要发送的数据并装包
bytes = "好的,明天见".getBytes();
packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("192.168.43.100"),8888);
socket.send(packet);
//关闭资源
socket.close();
}
}

浙公网安备 33010602011771号