Java学习之网络编程


一、网络基础

网络通信

  1. 概念:两台设备之间通过网络实现数据传输
  2. 网络通信:将数据通过网络从一台设备传输到另一台设备
  3. java.net包下提供一系列的类或接口,供我们使用

IP地址

  1. 概念:用于唯一标识网络中的每台计算机/主机
  2. 查看ip地址:ipconfig
  3. ip地址的表现形式: 点分十进制 xx.xx.xx.xx
  4. 每一个十进制数的范围:0-255
  5. ip地址=网络地址+主机地址 比如: 192.168.16.69
  6. IPv4使用4个字节32位表示
  7. IPv6使用128位表示地址 16个字节 是IPv4的4倍
    IPv4
    范围

域名

  1. 概念:将ip地址映射成域名, HTTP协议
  2. 好处:为了方便记忆,解决记ip的困难

端口号

  1. 概念:用于标识计算机上某个特定的网络程序
  2. 表示形式:以整数形式,范围 0-65535
  3. 0-1024 已经被占用, ssh 22,ftp 21,smtp 25,http 80
  4. 常见网络程序的端口号: tomcat 8080,mysql 3306,oracle 1521,sqlserver 1433

分层
TCP/IP


二、InetAddress

import org.junit.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @Author: mei_ming
 * @DateTime: 2022/10/1 0:13
 * @Description: 网络编程
 * 一、网络编程中有两个主要的问题:
 *  1. 如何准确地定位网络上一台或多台主机:定位主机上的特定的应用
 *  2. 找到主机后,如何可靠高效的进行数据传输
 *
 * 二、网络编程中的两个要素:
 *  1. 对应问题1,IP和端口号
 *  2. 对应问题2,提供网络通信协议:TCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)
 *
 * 三、通信要素一:IP和端口号
 *  1. IP:唯一的标识Internet上的计算机(通信实体)
 *  2. 在Java中使用InetAddress类代表IP
 *  3. IP分类:IPv4 和 IPv6、万维网 和 局域网
 *  4. 域名(方便记忆)
 *     www.baidu.com
 *  5. 回环地址 127.0.0.1
 *  6. 实例化InetAddress:getByName(String host)  /  getLocalHost()
 *         两个常用方法:getHostName()  / getHostAddress()
 *  7. 端口号:正在计算机上运行的进程
 *   范围:被规定为一个16位的整数,0-65535
 *   公认端口:0-1023  (HTTP: 80, FTP: 21, Telnet: 23)
 *   注册端口:1024-49151 分配给用户进程或应用程序 (Tomcat: 8080, MySQL: 3306, Oracle: 1521)
 *   动态/私有端口: 49152-65535
 *  8. 端口号与IP地址的组合得出一个网络套接字 : Socket
 *
 * 四、通信要素二:网络通信协议
 *
 *  网络通信协议:计算机网络中实现通信必须有一些约定,
 *  即通信协议,对速率、传输代码、代码结构。传输控制步骤、出错控制等制定标准。
 *
 *  TCP/IP协议簇
 *  传输层协议中有两个非常重要的协议:
 *      传输控制协议TCP(Transmission Control Protocol)
 *      用户数据报协议UDP(User Datagram Protocol)
 *  TCP/IP 以其两个主要协议:传输控制协议(TCP)和网络互联协议(IP)而得名,实际上是一组协议,
 *  包括多个具有不同功能且互为关联的协议。
 *  IP(Internet Protocol) 协议是网络层的主要协议,支持网间互联的数据通信。
 *  TCP/IP协议模型从更实用的角度出发,形成了高效的四层体系结构,即物理链路层、IP层、传输层和应用层
 *
 * TCP 和 UDP
 *  1. TCP协议
 *     使用TCP协议前,须先建立TCP连接,形成传输数据通道
 *     传输前,采用 ‘三次握手’ 方式,点对点通信,是可靠的
 *     TCP协议进行通信的两个应用进程: 客户端、服务端
 *     在连接中可进行大数据量的传输
 *     传输完毕,需释放已建立的连接(四次挥手),效率低
 *  2. UDP协议
 *     将数据、源、目的封装成数据包,不需要建立连接
 *     每个数据包限制在64k内
 *     发送不管对方是否准备好,接收方收到也不确认,故是不可靠的
 *     可以广播发送
 *     发送数据结束时无需释放资源,开销小,速度快
 *
 *
 */
public class InetAddressTest {
    @Test
    public void test1(){
        try {
            InetAddress inet1 = InetAddress.getByName("127.0.0.1");
            System.out.println(inet1);  // /127.0.0.1

            InetAddress inet2 = InetAddress.getByName("www.baidu.com");
            System.out.println(inet2);  // www.baidu.com/220.181.38.150
            System.out.println(inet2.getHostName());  // www.baidu.com
            System.out.println(inet2.getHostAddress());  // 220.181.38.149

            //快速获取本地IP
            InetAddress inet3 = InetAddress.getLocalHost();
            System.out.println(inet3);  // MING/172.16.3.213  (主机名/IP)
            InetAddress inet4 = InetAddress.getByName("MING");
            System.out.println(inet4);  // MING/172.16.3.213
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
}

三、Socket

基本介绍

  1. 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准
  2. 通信的两端都要有Socket,是两台机器间通信的端点
  3. 网络通信其实就是Socket间的通信
  4. Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
  5. 一般主动发起通信的属客户端,等待通信请求的为服务端

有两种编程方式:
TCP编程(可靠)/UDP编程(不可靠)

TCP实现

TCP三次握手
TCP四次挥手

案例一、客户端发送信息给服务端, 服务端将数据显示在控制台上

import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPTest1 {

    // 客户端
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        try {
            //1.创建Socket对象,指明服务端的ip和端口号
            socket = new Socket(InetAddress.getLocalHost(), 8888);
            //2.获取一个输出流,用于输出数据
            os = socket.getOutputStream();
            //3.写操作
            os.write("你好,服务端!我是客户端。".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 服务端
    @Test
    public void serve(){
        ServerSocket ss = null;
        Socket accept = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.创建ServerSocket对象,表明自己的端口
            ss = new ServerSocket(8888);
            //2.调用accept(),表示接收来自于客户端的socket
            accept = ss.accept();
            //3.获取输入流,以便控制台打印
            is = accept.getInputStream();
            //方式1、  (可能出现乱码,不推荐)
//            byte[] buffer = new byte[5];
//            int len;
//            while((len=is.read(buffer))!=-1){
//                System.out.println(new String(buffer,0,len));
//            }

            //方式2、
            baos = new ByteArrayOutputStream();
            byte[] bytes = new byte[5];
            int len;
            while((len=is.read(bytes))!=-1){
                baos.write(bytes,0,len);
            }
            System.out.println(baos.toString());
            System.out.println("来自于:"+accept.getInetAddress());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if (baos!=null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept!=null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

案例二、客户端发送文件给服务端,服务端将文件保存在本地

import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPTest2 {
    // 客户端
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        FileInputStream fis = null;
        try {
            //1.创建Socket对象,指明服务端的ip和端口号
            socket = new Socket(InetAddress.getLocalHost(), 8888);
            //2.获取一个输出流,用于输出数据
            os = socket.getOutputStream();
            //2.2 创建文件传输流,写入文件
            fis = new FileInputStream("101.jpg");
            //3.写操作
            byte[] bytes = new byte[5];
            int len;
            while((len=fis.read(bytes))!=-1){
                os.write(bytes,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 服务端
    @Test
    public void serve(){
        ServerSocket ss = null;
        Socket accept = null;
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            //1.创建ServerSocket对象,表明自己的端口
            ss = new ServerSocket(8888);
            //2.调用accept(),表示接收来自于客户端的socket
            accept = ss.accept();
            //3.获取输入流,以便控制台打印
            is = accept.getInputStream();
            fos = new FileOutputStream("101_download.jpg");

            byte[] buffer1 = new byte[5];
            int len1;
            while((len1=is.read(buffer1))!=-1){
                fos.write(buffer1,0,len1);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if (fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept!=null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

案例三、客户端发送文件给服务端,服务端将文件保存到本地,并返回"发送成功"给客户端,并关闭相应的连接

import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPTest3 {

    // 客户端
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        FileInputStream fis = null;
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            //1.创建Socket对象,指明服务端的ip和端口号
            socket = new Socket(InetAddress.getLocalHost(), 8888);
            //2.获取一个输出流,用于输出数据 
            os = socket.getOutputStream();
            //2.2 创建文件传输流,写入文件
            fis = new FileInputStream("101.jpg");
            //3.写操作
            byte[] bytes = new byte[5];
            int len;
            while((len=fis.read(bytes))!=-1){
                os.write(bytes,0,len);
            }
            //关闭数据输出,
            socket.shutdownOutput();

            //接收来自服务端的数据,并显示到控制台
            is = socket.getInputStream();
            baos = new ByteArrayOutputStream();
            byte[] bytes2 = new byte[5];
            int len2;
            while((len2=is.read(bytes2))!=-1){
                baos.write(bytes2,0,len2);
            }
            System.out.println(baos.toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭资源
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (baos!=null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 服务端
    @Test
    public void serve(){
        ServerSocket ss = null;
        Socket accept = null;
        InputStream is = null;
        FileOutputStream fos = null;
        OutputStream os = null;
        try {
            //1.创建ServerSocket对象,表明自己的端口
            ss = new ServerSocket(8888);
            //2.调用accept(),表示接收来自于客户端的socket
            accept = ss.accept();
            //3.获取输入流,以便控制台打印
            is = accept.getInputStream();
            fos = new FileOutputStream("101_download.jpg");
            byte[] buffer1 = new byte[5];
            int len1;
            while((len1=is.read(buffer1))!=-1){  //read() 阻塞式的,需手动关闭
                fos.write(buffer1,0,len1);
            }

            //发送提示给客户端
            os = accept.getOutputStream();
            os.write("服务端已接收图片".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept!=null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

案例三增强版:

import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPTest3_2 {

    // 客户端
    @Test
    public void client() throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(), 8888);
        String filePath = "e:\\100.jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
        // bytes 是filePath对应的字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        // 通过socket 获取输出流,将bytes数据传到服务端
        OutputStream os = socket.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write(bytes);
        socket.shutdownOutput();  // 结束标记

        //接收服务端消息
        InputStream inputStream = socket.getInputStream();
        String s = StreamUtils.streamToString(inputStream);
        System.out.println(s);
        inputStream.close();
        
        bos.close();
        bis.close();
        socket.close();
    }

    // 服务端
    @Test
    public void serve() throws IOException {
        ServerSocket serverSocket = new ServerSocket(8888);
        Socket socket = serverSocket.accept();
        InputStream is = socket.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        byte[] bytes = StreamUtils.streamToByteArray(bis);  // 得到一个字解数组
        String destFilePath = "src\\100.jpg";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);
        bos.close();

        //向客户端发送 收到
        OutputStream os = socket.getOutputStream();
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write("成功接收图片");
        bw.flush();  // 把内容刷新到数据通道
        socket.shutdownOutput();  // 结束标志

        bw.close();
        bis.close();
        socket.close();
        serverSocket.close();
    }
}

案例四、客户端,服务端通信(字符流实现)

import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPTest4 {

    // 客户端
    @Test
    public void client(){
        Socket socket = null;
        OutputStream os = null;
        InputStream is = null;
        BufferedWriter bw = null;
        BufferedReader br = null;
        try {
            //1.创建Socket对象,指明服务端的ip和端口号
            socket = new Socket(InetAddress.getLocalHost(), 8888);
            //2.获取一个输出流,用于输出数据
            os = socket.getOutputStream();
            //3.使用字符流的方式
            bw = new BufferedWriter(new OutputStreamWriter(os));
            bw.write("你好,服务器");
            bw.newLine();  //插入一个换行符,表示结束标志,读取时要用readLine()
            bw.flush();  //如果使用字符流,需要手动刷新

            //4.接收来自服务端的数据,并显示到控制台
            is = socket.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            System.out.println(line);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //5.关闭资源 (外层流)
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    // 服务端
    @Test
    public void serve(){
        ServerSocket ss = null;
        Socket accept = null;
        InputStream is = null;
        OutputStream os = null;
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //1.创建ServerSocket对象,表明自己的端口
            ss = new ServerSocket(8888);
            //2.调用accept(),表示接收来自于客户端的socket
            accept = ss.accept();
            //3.获取输入流,以便控制台打印,以字符流的方式读取
            is = accept.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String line = br.readLine();
            System.out.println(line);

            //发送提示给客户端
            os = accept.getOutputStream();
            // 使用字符输出流的方式,进行回复
            bw = new BufferedWriter(new OutputStreamWriter(os));
            bw.write("你好,客户端!");
            bw.newLine();   // 结束标志
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4. 关闭资源
            if (bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (accept!=null){
                try {
                    accept.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ss!=null){
                try {
                    ss.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

netstat 指令

  1. netstat -an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
  2. netstat -an | more 可以分页显示
    netstat

UDP实现

UDP说明:

  1. 没有明确的服务端和客户端,演变为数据的发送端和接收端
  2. 接收数据和发送数据是通过 DatagramSocket 对象完成的
  3. 将数据封装到DatagramPacket 对象 ,装包发送
  4. 当接收到DatagramPacket 对象,需要进行拆包,取出数据
  5. DatagramSocket 可以指定在哪个端口接收数据
import org.junit.Test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * @Author: mei_ming
 * @DateTime: 2022/10/1 13:05
 * @Description: UDP 网络通信
 *
 * 类 DatagramSocket 和 DatagramPacket 实现了基于UDP协议网络程序
 * UDP数据通过数据报套接字 DatagramSocket 发送和接收,系统不保证
 *  UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
 *
 * DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和
 *  端口号以及接收端的IP地址和端口号
 *
 * 发送端  接收端
 */
public class UDPTest {
    //发送端
    @Test
    public void sender(){
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket();
            String str = "我是UDP方式发送的导弹";
            byte[] bytes = str.getBytes();
            InetAddress localHost = InetAddress.getLocalHost();
            DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, localHost,8888);
            socket.send(packet);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket!=null){
                socket.close();
            }
        }
    }
    //接收端
    @Test
    public void receiver(){
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket(8888);
            byte[] bytes = new byte[100];
            DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length);
            socket.receive(packet);
            System.out.println(packet.getData());  //[B@32a1bec0
            System.out.println(new String(packet.getData(),0,packet.getLength()));  //我是UDP方式发送的导弹
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket!=null){
                socket.close();
            }
        }
    }
}

import org.junit.Test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

/**
 * @Author: mei_ming
 * @DateTime: 2022/10/1 21:56
 * @Description: UDP 例子2
 */
public class UDPTest2 {

    //发送端
    @Test
    public void udpsenderB() throws IOException {
        // 1. 创建 DatagramSocket 对象,准备在9998端口接收数据
        DatagramSocket socket = new DatagramSocket(9998);
        // 2. 将需要装包的数据 封装到 DatagramPacket 对象
        byte[] data = "hello 明天吃火锅!".getBytes();
        DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName("192.168.43.96"), 9999);
        socket.send(packet);

        //-----接送来自接收端的回复
        byte[] buf = new byte[1024];
        DatagramPacket packet1 = new DatagramPacket(buf, buf.length);
        socket.receive(packet1);
        byte[] data1 = packet1.getData();
        int length = packet1.getLength();
        String s = new String(data1, 0, length);
        System.out.println(s);
        socket.close();
        System.out.println("B端退出");
    }

    //接收端
    @Test
    public void udpreceiverA() throws IOException {
        //1. 创建一个 DatagramSocket 对象,准备在9999接收数据
        DatagramSocket socket = new DatagramSocket(9999);
        //2. 构建一个 DatagramPacket 对象,准备接收数据
        // udp最大数据报 为 64k
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        //3. 调用 接收方法,将通过网络传输的 DatagramPacket 对象
        //   填充到 packet 对象
        // 当有数据报发送到 本机的9999端口时,就会接收数据,
        //  否则 就会阻塞等待
        System.out.println("接收端A 登海接收数据...");
        socket.receive(packet);
        //4. 可以把packet 进行拆包,取出数据,并显示
        int length = packet.getLength();
        byte[] data = packet.getData();
        String s = new String(data, 0, length);
        System.out.println(s);

        //-------发送回复信息给发送端
        byte[] data2 = "好的,明天见!".getBytes();
        DatagramPacket packet1 = new DatagramPacket(data2, data2.length, InetAddress.getByName("192.168.43.96"), 9998);
        socket.send(packet1);

        socket.close();
        System.out.println("A端退出");
    }
}

作业1.

import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

/**
 * @Author: mei_ming
 * @DateTime: 2022/10/1 22:46
 * @Description: 按照输入内容,下载资源,若服务端没有想要的,则返回默认文件
 */
public class TCPTest5 {

    //客户端
    @Test
    public void client() throws IOException {
        Socket socket = new Socket(InetAddress.getLocalHost(),8888);
        OutputStream os = socket.getOutputStream();
        //Scanner 要写在main中
//        Scanner scanner = new Scanner(System.in);
//        System.out.println("请输入名字:");
//        String next = scanner.next();
//        String next = "100";  // 正常下载,100.jpg
        String next = "111";  // 下载 CCUT.jpg
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
        bw.write(next);
        bw.flush();
        socket.shutdownOutput();

        //--- 接收数据
        InputStream is = socket.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        byte[] bytes = StreamUtils.streamToByteArray(bis);  // 得到一个字解数组
        String destFilePath = "src\\"+next+".jpg";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);

        bos.close();
        bis.close();
        bw.close();
        socket.close();

    }

    //服务端
    @Test
    public void serve() throws IOException {
        ServerSocket ss = new ServerSocket(8888);
        System.out.println("服务端在8888端口监听 等待连接");
        Socket socket = ss.accept();
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String s = br.readLine();
        System.out.println("客户端希望下载的文件名="+s);

        String destFile = "";
        if("100".equals(s)){
            //发送100.jpg
            destFile="100";
        }else{
            //发送默认 CCUT.jpg
            destFile="CCUT";
        }
        String destFilePath = "e:\\"+destFile+".jpg";
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(destFilePath));
        byte[] bytes = StreamUtils.streamToByteArray(bis);  // 得到一个字解数组
        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
        bos.write(bytes);
        socket.shutdownOutput();  // 结束标志

        bos.close();
        bis.close();
        br.close();
        socket.close();
        ss.close();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值