一、网络编程介绍
1、网络编程:
是在网络通信写一下,在不同计算机上运行的程序可以进行数据传输。如:QQ聊天,A用户发送信息给B用户需要知道哪些条件呢?
-
网络编程三要素:
IP地址:设备在网络中的地址,唯一标识符。
端口:应用程序在设备中的唯一标识。
协议:数据在网络中传输的规则,常见的协议由UDP协议和TCP协议。
-
常见命令
ipconfig:查看本机ip地址。
ping ip地址:检查网络是否连通。
特殊IP地址:127.0.0.1本机地址
2、Inetaddress类
Inetaddress:此类表示internel(ip)地址。
常用方法:
方法名 说明 static InetAddress getByName(String host) 确定主机的ip地址 String getHostName() 获取ip地址的主机名 String getHostAddress() 返回文本显示中的ip地址字符串
二、UDP协议
1、协议:网络中,连接和通信的规则称之为网络通信协议
2、UDP协议
- 用户数据报协议
- UDP是面向无连接的通信协议
- 速度快,有大小限制最多发送64k,数据不安全,易丢失数据。
3、关键代码
DatagramSocket socket = new DatagramSocket() //码头
DatagramPacket socket = new DatagramPacket() //箱子
形象表示:
案例展示:
//发送方
public class SendTest1 {
public static void main(String[] args) throws IOException {
//建一个码头用于送货
//提供寄货的箱子
//东西都装到箱子里
//码头发货
//离开码头
DatagramSocket socket = new DatagramSocket(); //建一个码头用于送货
byte[] bytes = "要发送的东西".getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 10000;
DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port);//提供寄货的箱子//东西都装到箱子里
socket.send(packet);//码头发货
socket.close();//离开码头
}
}
//接收方
public class ReciveTest1 {
public static void main(String[] args) throws IOException {
//建一个码头(指定地址的码头收东西)
// 提供一个收东西的箱子(箱子要有一定的空间)
//接收箱子
//取出箱子里的东西
//离开码头
DatagramSocket socket = new DatagramSocket(10000);//建一个码头(指定地址的码头收东西)
byte[] bytes = new byte[1024];
DatagramPacket packet = new DatagramPacket(bytes, bytes.length);// 提供一个收东西的箱子(箱子要有一定的空间)
socket.receive(packet);//接收箱子
byte[] data = packet.getData();//取出箱子里的东西
System.out.println(new String(data));
socket.close();//离开码头
}
}
4、UDP的三种通信方式
-
单播:一对一发送接收
如上一个代码案例就是单播,一个接收一个发送,加一个死循环就可以一直发送和接收。
-
组播:一对一组发送接收
组播ip地址:224.0.0.0239.255.255.255(其中224.0.0.0224.0.0.255位预留的组播地址)
//发送方 public class SendTest2 { public static void main(String[] args) throws IOException { //建一个码头用于送货 //提供寄货的箱子 //东西都装到箱子里 //码头发货 //离开码头 DatagramSocket socket = new DatagramSocket(); byte[] bytes = "组播地址".getBytes(); InetAddress address = InetAddress.getByName("224.0.0.1");//发送端唯一区别ip地址 int port = 10000; DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port); socket.send(packet); socket.close(); } } //接收端 public class ReciveTest2 { public static void main(String[] args) throws IOException { //建一个码头(指定地址的码头收东西) // 提供一个收东西的箱子(箱子要有一定的空间) //取出箱子里的东西 //离开码头 MulticastSocket socket = new MulticastSocket(10000); //组播接收码头 byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.joinGroup(InetAddress.getByName("224.0.0.1")); //绑定组播地址,表示加入这一组中 socket.receive(packet); byte[] data = packet.getData(); System.out.println(new String(data)); socket.close(); } }
-
广播:一对所有发送接收(区别在于IP地址不同)
广播ip地址:255.255.255.255广播地址(局域网内所有用户能够接收到信息)
//发送方 public class SendTest { public static void main(String[] args) throws IOException { //建一个码头用于送货 //提供寄货的箱子 //东西都装到箱子里 //码头发货 //离开码头 DatagramSocket socket = new DatagramSocket(); Scanner scanner = new Scanner(System.in); while (true){ String next = scanner.next(); if ("886".equals(next)){ //输入886即停止退出循环 break; } byte[] bytes = next.getBytes(); InetAddress address = InetAddress.getByName("127.0.0.1");//255.255.255.255广播地址(局域网内所有用户能够接收到) int port = 10000; DatagramPacket packet = new DatagramPacket(bytes,bytes.length,address,port); socket.send(packet); } socket.close(); } } //接收端 public class ReciveTest { public static void main(String[] args) throws IOException { //建一个码头(指定地址的码头收东西) // 提供一个收东西的箱子(箱子要有一定的空间) //取出箱子里的东西 //离开码头 DatagramSocket socket = new DatagramSocket(10000); while (true){ byte[] bytes = new byte[1024]; DatagramPacket packet = new DatagramPacket(bytes, bytes.length); socket.receive(packet); byte[] data = packet.getData(); System.out.println(new String(data)); } // socket.close(); } }
三、TCP协议
1、UDP协议
-
传输控制协议
-
TCP是面向连接的通信协议
-
速度慢,无有大小限制,数据不安全。
//发送端
public class SendTest {
public static void main(String[] args) throws IOException {
//创建码头
Socket socket = new Socket("127.0.0.1",1000);
//获取流读写数据
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello".getBytes());
//释放资源
socket.close();
}
}
//接收方
public class ReceiveTest {
public static void main(String[] args) throws IOException {
//创建接收方码头
ServerSocket socket = new ServerSocket(1000);
//建立通道
Socket accept = socket.accept();
//读写出数据
InputStream inputStream = accept.getInputStream();
int b;
while ((b=inputStream.read())!= -1){
System.out.println((char) b);
}
//释放资源
socket.close();
}
}
2、三次握手
3、四次握手
案例优化
需求:1、从本地获取一份文件由客户端发送到服务端,服务端回应给客户端接收到了文件,并将文件添加到服务端保存在本地(图片为例)
2、多个客户端请求能够获取服务端文件(UUID保存图片名唯一,多线程用户模拟多个客户端需求,线程池节约系统资源)
//接收方 负责接收发送方文件并保存到本地,给发送方一个收到反馈
public class ReceiveTest003 {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(10000); //建立服务端码头
ThreadPoolExecutor pool = new ThreadPoolExecutor( //创建线程池
2, //核心线程数
4, //最大线程数
60,//空闲线程最大存活时间
TimeUnit.SECONDS, //空闲时间单位
new ArrayBlockingQueue(5),//阻塞个数
Executors.defaultThreadFactory(),//线程工厂
new ThreadPoolExecutor.AbortPolicy()//拒绝任务策略
);
while (true) {
Socket accept = socket.accept();//建立连接通道
ThreadTest threadTest = new ThreadTest(accept);//创建线程对象
Thread t1 = new Thread(threadTest);
// t1.start();
pool.submit(t1);//提交线程到线程池
}
// socket.close();
}
}
//线程任务类
class ThreadTest implements Runnable {
private Socket accept;
public ThreadTest(Socket accept) {
this.accept = accept;
}
BufferedOutputStream bos = null;
@Override
public void run() {
try {
InputStream is = accept.getInputStream(); //获取输入流
bos = new BufferedOutputStream(new FileOutputStream("D:\\IDEAworkspace\\basic_Code\\copy\\" + UUID.randomUUID().toString() + ".jpg"));//创建字节输出流用于保存文件位置(UUID提供不唯一的标识符做名称)
int b;
while ((b = is.read()) != -1) { //读取文件
bos.write(b); //写入文件
}
OutputStream os = accept.getOutputStream(); //获取输出流用于给发送端发送一个反馈
os.write("接收到了".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
accept.shutdownInput(); //关流
} catch (IOException e) {
e.printStackTrace();
}
try {
accept.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}