Files
Java-Basic-and-Advanced/网络编程.md
2026-01-07 16:14:38 +08:00

7.0 KiB
Raw Permalink Blame History

网络编程:

软件架构:

BS

Browser Server 浏览器 服务端

CS

Client Server 客户段 服务端

总结:

image-20251229162046866

网络编程三要素

IP

image-20251229162723116

特殊ip地址

image-20251229163018519

常用命令:

ipconfig:查看本机ip地址

ping:检查网络是否畅通

端口

image-20251229164022824

协议

UDP协议不可靠 速度快

案例:收发消息:

接收端:

public class Receive {
    public static void main(String[] args) throws Exception{
        //创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket(9999);
        //创建DatagramPacket对象
        DatagramPacket packet = new DatagramPacket(new byte[1024],1024);
        //接受信息
        socket.receive(packet);
        //拆包裹
        byte [] data =packet.getData();
        String msg = new String(data);
        String ip = packet.getAddress().getHostAddress();
        System.out.println("从"+ip+"ip发过来的信息"+msg);
        //释放资源
        socket.close();
    }
}

发送端:

public class Send {
    public static void main(String[] args) throws Exception{
        //创建DatagramSocket对象
        DatagramSocket socket = new DatagramSocket(8888);
        //准备材料
        String msg ="あんな别吃了";
        byte[] bytes = msg.getBytes();
        //打包包裹
        DatagramPacket packet = new DatagramPacket(bytes,
                bytes.length,
                InetAddress.getByName("127.0.0.1"),//参数为对方的ip对方的端口
                9999);
        socket.send(packet);
        socket.close();

    }
}

TCP协议可靠信息安全速度慢

image-20251229173457548

三次握手:

image-20251229184654252

四次挥手:

image-20251229185454457

大型案例:重点分析:

TCP上传文件

客户端

package com.ice.cat.test;

import java.io.*;
import java.lang.reflect.Type;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("10.104.117.228",9999);
        //获取输入输出流
        InputStream is = socket.getInputStream();
        OutputStream os = socket.getOutputStream();
        //将字节流转化为字符流,用来处理一些中文字符,再转化为字符缓冲流,可以读取一整行
        BufferedReader br =  new BufferedReader(new InputStreamReader(is));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        //写出文件的名字
        File file = new File("C:\\Users\\asus\\Pictures\\ariya.png");
        bw.write(file.getName());//没带换行符
        bw.newLine();
        bw.flush();
        //接受客户端反馈
        String flag = br.readLine();
        if (flag.equals("ok")){
            //继续上传文件
            //创建本地流,上传图片
            FileInputStream fle = new FileInputStream(file);
            byte [] bys = new byte[1024];
            int lne;
            while ((lne = fle.read(bys)) != -1){
                os.write(bys,0,lne);
            }
            fle.close();
            //重点:给服务端一个结束标记
            socket.shutdownOutput();//通俗理解,写出了一个-1标记
        }
        //读取服务端的返回消息消息
        String result = br.readLine();
        System.out.println(result);
        socket.close();
    }
}

服务端:

package com.ice.cat.test;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
import java.util.concurrent.*;

public class Server {
    public static void main(String[] args) throws Exception {
        //创建线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(4,
                6,
                60,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());

        ServerSocket server = new ServerSocket(9999);
        System.out.println("服务端开启,等待客户端连接");
        //响应请求
        //多次响应上传图片,用循环包裹
        while (true) {
            Socket socket = server.accept();
            pool.submit(new SubmitTask(socket));
        }
    }
}

线程池代码:为实现多次运行,可在不同线程进行调用

package com.ice.cat.test;

import java.io.*;
import java.net.Socket;
import java.util.UUID;

public class SubmitTask implements Runnable{
private Socket socket;
public SubmitTask(Socket socket){
    this.socket = socket;
}
    @Override
    public void run() {

        try {
            InputStream is = socket.getInputStream();
            OutputStream os = socket.getOutputStream();
            //将字节流转化为字符流,用来处理一些中文字符,再转化为字符缓冲流,可以读取一整行
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
            //接受文件名字
            String resultName = br.readLine();
            //给用户端反馈
            bw.write("ok");
            bw.newLine();
            bw.flush();
            //读取客户端上传的文件,注意写出上传的位置
            //为避免文件名字重复使用UUID方法
            File file = new File("C:\\Users\\asus\\Desktop\\JAVA", UUID.randomUUID().toString() + resultName);
            //准备本地的输出流,将网络服务端数据写入到指定位置
            FileOutputStream fos = new FileOutputStream(file);
            //读取网络流数据,写入到本地文件
            int lne;
            byte[] bys = new byte[1024];
            //is为网络输入流没有关联文件不可能有-1
            while ((lne = is.read(bys)) != -1) {
                fos.write(bys, 0, lne);
            }
            fos.close();
            //回写给客户段消息
            bw.write("上传成功");
            bw.newLine();
            bw.flush();
            //关流
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

补充点若文件名重复则使用UUID.randomUUID().toString()来生成随机名字