2.网络编程
2.1. 通信协议
-
TCP、UDP对比
-
TCP 打电话
-
连接,稳定
-
三次握手,四次挥手
三次握手 A: 你瞅啥? B: 瞅你咋地? A:干一场!四次挥手 A:我要走了 B: 你真的要走了吗? B:你真的真的要走了吗? A:我真的要走了
-
客户端、服务端
-
传输完成,释放连接,效率低
-
-
UDP 发短信
- 不连接,不稳定
- 客户端,服务端,没有明确的界限
- 不管有没有准备好,都可以发给你
- 导弹
- DDOS:洪水供给!(饱和攻击)
-
2.2. Tcp上传测试
1、TcpUploadClient.javapackage com.hzs.basic.inet;import java.io.*;
import java.net.Inet4Address;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;/*** @author Cherist Huan* @version 1.0* @date 2021/6/8 11:39* @note 文件上传客户端*/
public class TcpUploadClient {public static void main(String[] args) throws IOException {// 1、创建一个Socket连接Socket socket = new Socket(Inet4Address.getByName("127.0.0.1"),9999);// 2、创建一个输出流OutputStream os = socket.getOutputStream();// 3、读取文件// FileInputStream fis = new FileInputStream(new File(String.valueOf(TcpUploadClient.class.getResource("6.jpg"))));// URL resource = TcpUploadClient.class.getResource("/images/6.jpg");// FileInputStream fis = new FileInputStream(resource.getPath());File file = new File("java-test-questions-06/src/main/resources/images/6.jpg");// File file = new File("images/6.jpg");System.out.println(file.getAbsolutePath());FileInputStream fis = new FileInputStream(file);// 4、写出文件byte[] buffer = new byte[1024];int len;while((len = fis.read(buffer))!= -1){os.write(buffer,0,len);}// 通知服务器,我已经传输完毕了socket.shutdownOutput(); // 我已经传输完毕// 接受服务器的响应,确定服务器接受完毕,才能关闭连接InputStream is2 = socket.getInputStream();byte[] buffer2 = new byte[1024];int len2;ByteArrayOutputStream baos = new ByteArrayOutputStream();while((len2 = is2.read(buffer2))!= -1){baos.write(buffer2,0,len2);}System.out.println(baos.toString());// 5、关闭资源baos.close();fis.close();os.close();socket.close();}
}
2、TcpUploadServer.javapackage com.hzs.basic.inet;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;/*** @author Cherist Huan* @version 1.0* @date 2021/6/8 11:39* @note 文件上传服务端*/
public class TcpUploadServer {public static void main(String[] args) throws IOException {// 1、创建ServerSocketServerSocket serverSocket = new ServerSocket(9999);// 2、创建Socket监听Socket socket = serverSocket.accept();// 3、获取输入流InputStream is = socket.getInputStream();// 4、文件输出// URL resource = TcpUploadClient.class.getResource("/images/6_receive.jpg");
// //FileOutputStream fos = new FileOutputStream(new File(resource.getPath()));
// FileOutputStream fos = new FileOutputStream(resource.getPath());File file = new File("java-test-questions-06/src/main/resources/images/6receive.jpg");//File file = new File("images/6_receive.jpg");FileOutputStream fos = new FileOutputStream(file);byte[] buffer;buffer = new byte[1024];int len;while((len = is.read(buffer))!= -1){fos.write(buffer,0,len);}// 通知客户端,我已经接受完毕OutputStream os = socket.getOutputStream();os.write("服务端返回,服务端已经接受完毕了".getBytes());// 5、关闭资源os.close();fos.close();is.close();socket.close();serverSocket.close();}
}
总结:
-
客户端
- 建立socket连接
- 创建一个输出管道流
- 读取需要上传的文件
- 将文件写出到管道流
- 通知服务器,我已经传输完毕
- 接受服务器的响应,确定服务器接受完毕,才能关闭连接
- 关闭资源
-
服务端
- 建立ServerSocker端口服务
- 创建Socket监听,返回Socket
- 获取输入流
- 获取输入流中文件输出
- 通知客户端,我已经接受完毕
- 关闭资源
2.3. Udp 传输
1、UdpClient.javapackage com.hzs.basic.inet;import java.io.IOException;
import java.net.*;/*** @Author Cherist Huan* @Date 2021/6/10 10:41* @Version 1.0*/
public class UdpClient {public static void main(String[] args) throws IOException {// System.out.println(("AB".getBytes()).length);//2// 1、建立一个SocketDatagramSocket socket = new DatagramSocket();// 2、建包String msg = "Hello Cherist Huan!";InetAddress byName = Inet4Address.getByName("127.0.0.1");int port = 9090;DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,byName,port);// 3、发送包socket.send(datagramPacket);// 4、关闭流socket.close();}
}
2、UdpServer.javapackage com.hzs.basic.inet;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;/*** @Author Cherist Huan* @Date 2021/6/10 10:57* @Version 1.0*/
public class UdpServer {public static void main(String[] args) throws IOException {// 1、开放端口DatagramSocket datagramSocket = new DatagramSocket(9090);// 2、接受数据包byte[] buffer = new byte[1024];DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);datagramSocket.receive(packet);// 阻塞式接受System.out.println(new String(packet.getData(),0,packet.getLength()));// 关闭流datagramSocket.close();}
}
2.4. Udp聊天室(多线程)
1、TalkSend.java
package com.hzs.basic.inet;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;/*** @Author Cherist Huan* @Date 2021/6/10 15:24* @Version 1.0*/
public class TalkSend implements Runnable {DatagramSocket socket = null;BufferedReader reader = null;private int fromPort;private int toPort;private String toIp;public TalkSend(int fromPort, int toPort, String toIp) {this.fromPort = fromPort;this.toPort = toPort;this.toIp = toIp;try {socket = new DatagramSocket(fromPort);reader = new BufferedReader(new InputStreamReader(System.in));} catch (SocketException e) {e.printStackTrace();}}public void run() {while(true){try {String data = reader.readLine();byte[] dataBytes = data.getBytes();DatagramPacket packet = new DatagramPacket(dataBytes,0,dataBytes.length,new InetSocketAddress(this.toIp,this.toPort));socket.send(packet);if(data.equals("bye")){break;}} catch (IOException e) {e.printStackTrace();}}socket.close();}
}2、TalkReceive.java
package com.hzs.basic.inet;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;/*** @Author Cherist Huan* @Date 2021/6/10 15:44* @Version 1.0*/
public class TalkReceive implements Runnable{DatagramSocket socket = null;private int port;private String msg;public TalkReceive(int port,String msg){this.port = port;this.msg = msg;try {socket = new DatagramSocket(port);} catch (SocketException e) {e.printStackTrace();}}public void run() {while(true){try {byte[] container = new byte[1024];DatagramPacket packet = new DatagramPacket(container, 0, container.length);socket.receive(packet);//阻塞式接受包裹// 断开连接 byebyte[] data = packet.getData();String receiveData = new String(data,0,data.length);System.out.println(msg+":"+receiveData);if(receiveData.equals("bye")){break;}} catch (IOException e) {e.printStackTrace();}}socket.close();}
}3、TalkStudent.java
package com.hzs.basic.inet;/*** @Author Cherist Huan* @Date 2021/6/10 15:56* @Version 1.0*/
public class TalkStudent {public static void main(String[] args) {// 开启两个线程new Thread(new TalkSend(7777,9999,"localhost")).start();//学生端接受线程端口(服务端口 8888)new Thread(new TalkReceive(8888,"老师说")).start();}
}4、TalkTeacher.java
package com.hzs.basic.inet;/*** @Author Cherist Huan* @Date 2021/6/10 16:04* @Version 1.0*/
public class TalkTeacher {public static void main(String[] args) {// 开启两个线程new Thread(new TalkSend(6666,8888,"localhost")).start();//老师端接受线程端口(服务端口 9999)new Thread(new TalkReceive(9999,"学生说")).start();}
}
2.5 对比总结
Java网络编程中,TCP(传输控制协议)和UDP(用户数据报协议)是两种主要的传输层协议。它们各有特点和适用场景。
TCP传输
特点:
- 面向连接:TCP在传输数据之前需要先建立连接,传输完成后需要断开连接。
- 可靠传输:TCP通过序列号、确认应答、超时重传等机制确保数据的可靠传输。
- 流量控制:TCP通过滑动窗口机制进行流量控制,避免发送方发送速率过快导致接收方处理不过来。
- 拥塞控制:TCP通过慢开始、拥塞避免、快重传、快恢复等算法进行拥塞控制,避免网络拥塞。
应用场景:
- 需要可靠传输的应用,如文件传输、电子邮件等。
- 对数据传输顺序有要求的应用,如网页浏览、在线视频等。
UDP传输
特点:
- 无连接:UDP在传输数据之前不需要建立连接,每个数据报都是一个独立的信息。
- 不可靠传输:UDP不保证数据的可靠传输,不进行流量控制和拥塞控制。
- 开销小:由于UDP协议简单,传输开销小,适合实时性要求高的应用。
应用场景:
- 实时性要求高的应用,如音频、视频流等。
- 允许一定程度上数据丢失的应用,如实时游戏、实时股市行情等。