个人主页:Hello Code.
本文专栏:Java零基础指南
更多相关内容请点击前往 Java零基础指南 查看
如有问题,欢迎指正,一起学习~~
网络编程:在网络通信协议下,不同计算机上运行的程序,可以进行数据传输
网络编程三要素
IP:全称“互联网协议地址”,也称IP地址。是分配给上网设备的数字标签。常见的IP分类为:ipv4和ipv6
通过域名访问服务器->域名通过DNS服务器解析为IP地址传递回去->计算机再通过解析好的IP地址访问相应的服务器->服务器返回数据展示在浏览器上
IPv4
点分十进制表示法:192.168.1.66
IPv6
采用128位地址长度,分成8组,每16位分为一组
省略前面的0:2001:DB8:0:23:8:800:200C:417A
采用0位压缩表示法:FF01::1101
常用命令
ipconfig
:查看本机IP地址ping IP地址
:检查网络是否连通为了方便我们对IP地址的获取和操作,Java提供了一个类InetAddress供我们使用
InetAddress:此类表示Internet协议(IP)地址
常用方法
static InetAddress getByName(String host)
:确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址String getHostName()
:获取此IP地址的主机名String getHostAddress()
:返回文本显示中的IP地址字符串端口:应用程序在设备中唯一的标识
端口号:用两个字节表示的整数,它的取值范围是0~65535
其中0~1023之间的端口号用于一些知名的网络服务或者应用
在自己使用时使用1024以上的端口号就可以了
注意:一个端口号只能被一个应用程序使用
在计算机网络中,连接和通信的规则被称为网络通信协议
UDP协议
用户数据报协议(User Datagram Protocol)
速度快,有大小限制,一次最多发送64K,数据不安全,容易丢失数据
TCP协议
速度慢,没有大小限制,数据安全
发送数据步骤
代码实现
public class Demo{
public static void main(String[] args) throws IOException{
// 创建发送端对象
DatagramSocket ds = new DatagramSocket();
// 数据打包 DatagramPacket(byte[] buf, int length, InetAddress, int port)
String s = "需要发送的数据";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
// 发送数据
ds.send(dp);
// 释放资源
ds.close();
}
}
步骤
代码
public class Demo{
public static void main(String[] args) throws{
// 创建接收端对象------参数表示从10000端口接收数据
DatagramSocket ds = new DatagramSocket(10000);
// 创建箱子
byte[] bytes = new bytes[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
// 接收数据
ds.receive(dp);
// 获取数据
byte[] data = dp.getData();
System.out.println(new String(data));
// 释放资源
ds.close();
}
}
在这里运行时必须先运行接收端再运行发送端(否则都发送完了才运行接收端就接收不到了)
如果接收端在启动之后没有接收到数据,会阻塞
在接收数据的时候,需要调用一个getLength方法,表示接收到了多少字节
// 发送端
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Scanner;
public class ClientDemo {
public static void main(String[] args) throws IOException{
Scanner sc = new Scanner(System.in);
DatagramSocket ds = new DatagramSocket();
while(true){
String s = sc.nextLine();
if("886".equals(s)) break;
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
ds.send(dp);
}
ds.close();
}
}
// 接收端
package UDP;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class ServerDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10000);
while(true){
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data, 0, length));
}
// ds.close();
}
}
单播:一个发送端通过一个路由器只发送给一个接收端(一对一)
组播:一个发送端通过一个路由器发送给一组接收端(一对多)
其中224.0.0.0~224.0.0.255为预留的组播地址,不可用
在创建箱子后,还要把当前电脑添加到这一组中
// 组播的发送端
public static void main(String[] args) throws IOException{
DatagramSocket ds = new DatagramSocket();
String s = "Hello Word";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("224.0.1.0");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
ds.send(dp);
ds.close();
}
// 接收端
public static void main(String[] args) throws IOException{
MulticastSocket ms = new MulticastSocket(10000);
DatagramPacket dp = new DatagramPacket(new byte[1024], 1024);
// 把当前计算机绑定一个组播地址
ms.joinGroup(InetAddress.getByName("224.0.1.0"));
// 接收数据
ms.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data, 0, length));
ms.close();
}
广播:一个发送端通过一个路由器发送给该局域网下所有接收端(一对所有)
// 发送端
public static void main(String[] args) throws IOException{
DatagramSocket ds = new DatagramSocket();
String s = "广播发送端";
byte[] bytes = s.getBytes();
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
ds.sent(dp);
ds.close();
}
// 接收端
public class ServerDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10000);
while(true){
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
ds.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
System.out.println(new String(data, 0, length));
}
ds.close();
}
}
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象
发送端:
Socket
接收端:ServerSocket
通信之前要保证连接已经建立
通过Socket产生IO流来进行网络通信
Socket(String host, int port)
OutputStream getOutputStream()
void close()
代码实现
// 客户端
public static void main(String[] args) throws IOException{
Socket socket = new Socket("127.0.0.1", 10000);
OutputStream os = socket.getOutputStream();
os.write("hello".getBytes());
os.close();
socket.close();
}
ServerSocket(int port)
Socket accept()
InputStream getInputStream()
void close()
代码实现
// 服务端
public static void main(String[] args){
ServerSocket ss = new ServerSocket(10000);
Socket accept = ss.accept(); // 没有客户端连接的话,就会死等,不执行后续代码,即阻塞
InputStream is = accept.getInputStream();
int b;
while((b = is.read()) != -1){
System.out.print((char) b);
}
is.close();
ss.close();
}
客户端写数据,服务端读数据
客户端创建对象并连接服务器,此时是通过三次握手协议保证服务器之间的连接
针对客户端,是往外写的,所以是输出流;而服务端是往进读的,所以是输入流
read方法也是阻塞的
在关流的时候,还多了一个往服务器写结束标记的动作
最后一步断开连接,会通过四次挥手协议保证连接终止
保证客户端与服务器之间建立连接
保证客户端与服务端取消连接,成功终止连接
练习一
// 客户端
package TCP;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.OutputStream;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10000);
OutputStream os = socket.getOutputStream();
os.write("hello".getBytes());
socket.shutdownOutput(); // 仅仅关闭输出流,并写一个结束标记,对socket没有任何影响
InputStream is = socket.getInputStream();
int b;
while ((b = is.read()) != -1) {
System.out.print((char) b);
}
is.close();
os.close();
socket.close();
}
}
// 服务端
package TCP;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.InputStream;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10000);
Socket accept = ss.accept();
InputStream is = (InputStream) accept.getInputStream();
int b;
while ((b = is.read()) != -1) {
System.out.print((char) b);
}
OutputStream os = accept.getOutputStream();
os.write("who?".getBytes());
os.close();
is.close();
accept.close();
ss.close();
}
}
练习二
// 客户端
package TCP;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ClientDemo2 {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 10000);
// 本地的流,读取本地文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.png"));
OutputStream os = socket.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(os);
int b;
while ((b = bis.read()) != -1) {
bos.write(b); // 通过网络写到服务器中
}
// 给服务器一个结束标记
socket.shutdownOutput();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
socket.close();
bis.close();
}
}
// 服务器
package TCP;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo2 {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10000);
Socket accept = ss.accept();
// 网络中的流,从客户端读取数据的
BufferedInputStream bis = new BufferedInputStream(accept.getInputStream());
// 本地的IO流,把数据写到本地中,实现永久化存储
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\copy.png"));
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
bw.write("上传成功!");
bw.newLine();
bw.flush();
accept.close();
ss.close();
bos.close();
}
}
UUID uuid = UUID.randomUUID();
生成一个随机且唯一的uiduuid.toString();
转换为字符串推荐阅读:【Java】基础知识加强