Java网络编程

JavaSE

网络编程

一.网络编程三要素:

  1. IP
  2. Port
  3. 传输层协议
1.作用

应用层:根据业务逻辑产生数据;根据业务逻辑接收数据。
下面的层(在Java中使用Socket类对象(不同的传输层协议,对应不同的Socket类)来完成):底层的进程之间数据的传输(字节数据)。

通信的每一端目的地址:
IP地址(主机)+端口号(进程 1024—65535)

传输层协议:
规定数据传输的方式:UDP,TCP
UDP:传输 数据报包(包含目标地址 ip+port)
TCP:建立连接,用流来传输数据。大量数据和连续传输时使用

不同的协议对于不同的Socket类,来实现TCP,UDP协议的输出传输。
在这里插入图片描述

二.UDP编程

1.版本1代码:
发送端:
/*
1.创建UDP的Socket对象(DatagramSocket)用于接收和发送。
2.将数据打包成数据报包
3.用Socket对象传输数据报包
4.释放Socket资源
*/
1.
//UDP的Socket类(DatagramSocket)对象创建:
DatagramSocket(int port) //本机ip + 指定端口号port
2.
//创建数据报包对象
DatagramPacket(byte[] bytes, int offset, int length, InetAddress address, int port) //发送到指定ip+port的目的地址。
3.
//利用DatagramSocket对象的send方法发送数据报包
public void send(DatagramPacket p)
DatagramSocket对象.send(DatagramPacket对象)
4.
//释放资源
DatagramSocket对象.close()

import java.io.IOException;
import java.net.*;
public class Sender {
    public static void main(String[] args) throws IOException {
        String s = "hello";
        DatagramSocket datagramSocket = new DatagramSocket(10086);  //创建UDP传输的Socket对象,该对象可以发送数据报包,可以接收数据报包。
        
        byte[] bytes = s.getBytes();
        InetAddress targetIp = InetAddress.getByName("192.168.17.1"); //获取本机ip(因为我们是在同个电脑通信)
        int targetPort = 8888;
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, targetIp, targetPort); //创建一个数据报包。参数有字节数组和其偏移量,长度。同时还有目标主机的IP地址和端口号
        datagramSocket.send(datagramPacket); //调用用于UDP协议的Socket类对象的send方法,发送数据报包。
   		
   		datagramSocket.close(); // 释放资源
    }
}

即使没有接收端,UDP发送端也可以发送,所以可以看出UDP协议是一种无连接的不可靠协议。

接收端:
/*
1.首先创建一个用于UDP协议的Socket类对象
2.创建一个数据报包稍后用于接收数据
3.Socket类对象的receive()方法接收数据
4.释放资源
5.解析数据
*/
1.
//接收端的DatagramPacket类对象构造方法有所不同
DatagramPacket(byte[] buf, int offset, int length) //buf为传入数据报包的缓冲区;offset为偏移量,length为读取字节数。

2.
//从套接字Socket中接收数据报包
public void receive(DatagramPacket p) //数据包中不仅有字节数组的信息还包含发送端的ip和port端口号,是一个阻塞方法。
/*
注意事项:
1. receive方法是一个阻塞方法
2. 当我们两次运行Receiver接收端,会出现BindException: Address already in use (ip + port)
即一个端口号只能同时绑定一个进程,所以当两次启动Receiver端的时候,相当于要让两个进程绑定同一个端口号,这是不允许的。
*/
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        DatagramSocket datagramSocket = new DatagramSocket(8888); //与发送端要对应

        byte[] bytes = new byte[1024]; //我们一般知道应用传过来的数据的大概大小,一般1024整数倍。
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length); //接受端的数据报包的构造方法与发送端有所不同。
        datagramSocket.receive(datagramPacket);  //在接收到数据前一直处于阻塞状态

        datagramSocket.close();
        byte[] data = datagramPacket.getData(); //data与bytes相同
        int off = datagramPacket.getOffset(); //偏移量
        int length = datagramPacket.getLength(); //实际传输来的字节大小。

        String s = new String(data,off,length); //解析字节数组
        System.out.println(datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "," + s);   //getAddress()返回一个InetAddress类型的数据;getPort()返回一个int类型的数据
    }
}
2.版本2代码:

增加了发送端多次输入和发送终止条件。

发送端:
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
版本二:增加多次输入,增加可退出。
 */
public class Sender {
    public static void main(String[] args) throws IOException {
        String data;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));  //缓冲字符流
        DatagramSocket datagramSocket = new DatagramSocket(10086);
        while((data = br.readLine()) != null) {
            sendData(data, datagramSocket);
            if("886".equals(data)) {  //退出条件
                break;
            }
        }
        datagramSocket.close();
    }
           //ctrl + alt + m抽成一个方法。
    private static void sendData(String s, DatagramSocket datagramSocket) throws IOException {
        byte[] bytes = s.getBytes();
        InetAddress targetIp = InetAddress.getByName("192.168.17.1");
        int targetPort = 8888;
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, targetIp, targetPort);   //每次发送的内容不同,所以要多次创建,把内容打包进去
        datagramSocket.send(datagramPacket);
    }
}

接收端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        boolean flag = true;  //欺骗编译器而用
        DatagramSocket datagramSocket = new DatagramSocket(8888);
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);  //这里的数据报包也类似一个容器,接收用的,只需要创建一次。
        while(flag) {
            boolean isFinish = receiveData(datagramSocket, datagramPacket);
            if(isFinish)
                break;
        }
        datagramSocket.close();
    }

    private static boolean receiveData(DatagramSocket datagramSocket, DatagramPacket datagramPacket) throws IOException {

        datagramSocket.receive(datagramPacket);  //在接收到数据前一直处于阻塞状态
        byte[] data = datagramPacket.getData();
        int off = datagramPacket.getOffset();
        int length = datagramPacket.getLength();

        String s = new String(data,off,length);
        System.out.println(datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "," + s);
        if("886".equals(s)) {
            return true;
        }
        return false;
    }
}
3.版本3代码:

实现双向发送和识别886退出。但是存在缺点,只能一句一句来回发,退出需要发送端提出886,接收端不管回复什么,都会结束程序。

发送端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
版本三:实现收发。
 */
public class Sender {
    public static void main(String[] args) throws IOException {
        String data;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        DatagramSocket datagramSocket = new DatagramSocket(10086);
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
        while((data = br.readLine()) != null) {
            sendData(data, datagramSocket);
            receiverResponse(datagramSocket,datagramPacket);
            if("886".equals(data)) {
                break;
            }
        }
        datagramSocket.close();
    }

    private static void receiverResponse(DatagramSocket datagramSocket, DatagramPacket datagramPacket) throws IOException {
        datagramSocket.receive(datagramPacket);
        byte[] receiveData = datagramPacket.getData();
        int off = datagramPacket.getOffset();
        int length = datagramPacket.getLength();
        String s = new String(receiveData, off, length);
        System.out.println(datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "," + s);
    }

    private static void sendData(String s, DatagramSocket datagramSocket) throws IOException {
        byte[] bytes = s.getBytes();
        InetAddress targetIp = InetAddress.getByName("192.168.17.1");
        int targetPort = 8888;
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, targetIp, targetPort);
        datagramSocket.send(datagramPacket);
    }
}

接收端

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        boolean flag = true;
        DatagramSocket datagramSocket = new DatagramSocket(8888);
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while(flag) {
            boolean isFinish = receiveData(datagramSocket, datagramPacket);

            receiverSend(datagramSocket, datagramPacket, br);

            if(isFinish)
                break;
        }
        datagramSocket.close();
    }

    private static void receiverSend(DatagramSocket datagramSocket, DatagramPacket datagramPacket, BufferedReader br) throws IOException {
        String s = br.readLine();
        byte[] responseBytes = s.getBytes();
        DatagramPacket responsePacket = new DatagramPacket(responseBytes,0,responseBytes.length,datagramPacket.getAddress(),datagramPacket.getPort());
        datagramSocket.send(responsePacket);
    }

    private static boolean receiveData(DatagramSocket datagramSocket, DatagramPacket datagramPacket) throws IOException {

        datagramSocket.receive(datagramPacket);  //在接收到数据前一直处于阻塞状态
        byte[] data = datagramPacket.getData();
        int off = datagramPacket.getOffset();
        int length = datagramPacket.getLength();

        String s = new String(data,off,length);
        System.out.println(datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "," + s);
        if("886".equals(s)) {
            return true;
        }
        return false;
    }
}

4.版本4代码:

实现了同时收发,不需要发一句等一句收;
发送886之后,可以等待接收方的回复。只有接收和发送都有886时,才结束程序。

发送Task
package day21.network.edition4.oneperson;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class SendTask implements Runnable {
    DatagramSocket socket;
    private static int targetPort;
    private static InetAddress targetIp;
    public SendTask(DatagramSocket socket, String targetIp, int targetPort) throws UnknownHostException {
        this.socket = socket;
        this.targetIp = InetAddress.getByName(targetIp);
        this.targetPort = targetPort;
    }
    @Override
    public void run() {
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        try {
            String s;
            while ((s = br.readLine()) != null) {
                sendData(s,socket);
                if("886".equals(s)) {
                    synchronized (socket) {
                        OnePerson.isSendOffline = true;
                    }
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static void sendData(String s, DatagramSocket datagramSocket) throws IOException {
        byte[] bytes = s.getBytes();
        DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, targetIp, targetPort);
        datagramSocket.send(datagramPacket);
    }
}

接收Task
package day21.network.edition4.oneperson;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class ReceiveTask implements Runnable {
    DatagramSocket socket;
    public ReceiveTask(DatagramSocket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        byte[] bytes = new byte[1024];
        DatagramPacket datagramPacket = new DatagramPacket(bytes,0,bytes.length);
        try {
            while(true) {
                boolean isFinish = receiveData(socket,datagramPacket);
                if(isFinish)
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            while(true) {
                synchronized (socket) {
                    if(OnePerson.isSendOffline) {
                        break;
                    } else {
                        try {
                            socket.wait(100);  //等待100毫秒
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            socket.close();
        }
    }
    private static boolean receiveData(DatagramSocket datagramSocket, DatagramPacket datagramPacket) throws IOException {

        datagramSocket.receive(datagramPacket);  //在接收到数据前一直处于阻塞状态
        byte[] data = datagramPacket.getData();
        int off = datagramPacket.getOffset();
        int length = datagramPacket.getLength();

        String s = new String(data,off,length);
        System.out.println(datagramPacket.getAddress() + ":" + datagramPacket.getPort() + "," + s);
        if("886".equals(s)) {
            return true;
        }
        return false;
    }
}
Person
package day21.network.edition4.oneperson;

import java.net.DatagramSocket;
import java.net.SocketException;
import java.net.UnknownHostException;

public class OnePerson {
    public static boolean isSendOffline = false;
//    public static Object closeLock = new Object();
    public static void main(String[] args) throws SocketException, UnknownHostException {
        DatagramSocket socket = new DatagramSocket(8888);
        SendTask sendTask = new SendTask(socket,"127.0.0.1",10086);
        ReceiveTask receiveTask = new ReceiveTask(socket);
        new Thread(sendTask).start();
        new Thread(receiveTask).start();
    }
}

三.TCP编程

1.基本:客户端发送与服务器接收

在这里插入图片描述
发送端(客户端)直接Socket建立连接。接收端(服务器)需要先建立ServerSocket接收连接请求后获得Socket对象和客户端进行通信。流的创建依靠Socket对象。

/*
客户端发送:
1.创建一个TCP客户端Socket对象实现收发,明确服务器的地址。建立成功则表示已连接,建立失败则连接不了终止程序
2.建立连接成功,则可以用Socket对象来获取流传输数据
3.向流读取或者输出数据
4.释放资源
 */
1.public class Socket  //此类实现 客户端 套接字
2.public Socket(String host, int port) //构造方法,指定服务器地址,Socket地址是 本地ip + 随机分配的port

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流
        String s = "hello, tcp!";
        byte[] bytes = s.getBytes();
        output.write(bytes);  //利用流发送数据
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
    }
}


import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
TCP中,接收端也称为服务器端。

服务器接收
1.创建TCP服务器ServerSocket对象,指定端口进行监听
2.如果监听到连接请求,则成功创建一个Socket对象来实现数据收发
3.由于该服务器要实现接收,所以该用Socket对象创建一个InputStream对象来接收数据
4.释放资源。
 */
 
1.public class ServerSocket //实现服务器套接字。服务器套接字等待请求通过网络传输传入
2.public ServerSocket(int port) //构造函数,指定其本身的服务器端口。客户端以此为port传输数据过来
3.public Socket accept() //ServerSocket的accept方法将监听并接收套接字(客户端在创建套接字时)的连接。阻塞方法

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();  //阻塞方法
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes,0,len);
        System.out.println("来自" + socket.getInetAddress() + ":" + socket.getPort() + "的" + s);   //可以通过Socket对象的getInetAddress方法和getPort方法分别获取到发送端的IP和端口号。与UDP的DatagramPacket类似。
        socket.close();   //关闭两个套接字
        serverSocket.close();
    }
}
2.服务器给客户端反馈消息
//客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流
        String s = "hello, tcp!";
        byte[] bytes = s.getBytes();
        output.write(bytes);  //利用流发送数据

        InputStream inputStream = socket.getInputStream();
        int len;
        byte[] readBytes = new byte[1024];
        len = inputStream.read(readBytes);
        System.out.println(new String(readBytes,0,len));
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
    }
}

//服务器
package day22.tcp.exercise01;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
1.创建TCP服务器ServerSocket对象,指定端口,进行监听
2.如果监听到连接请求,则创建一个Socket对象来实现数据收发
3.由于该服务器要实现接收,所以该用Socket对象创建一个InputStream对象来接收数据
4.释放资源。
 */
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        String s = new String(bytes,0,len);
        System.out.println("来自" + socket.getInetAddress() + ":" + socket.getPort() + "的" + s);

        OutputStream outputStream = socket.getOutputStream();
        String str = "已收到";
        outputStream.write(str.getBytes());

        socket.close();
        serverSocket.close();
    }
}
3.客户端发给服务器多次,服务器输出到控制台
//客户端
import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while((s = reader.readLine()) != null) {
            byte[] bytes = s.getBytes();
            output.write(bytes);  //利用流发送数据
        }
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
    }
}

//服务器
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        int len;
        byte[] bytes = new byte[1024];
        while((len = in.read(bytes)) != -1) {
            String s = new String(bytes,0,len);
            System.out.println("来自" + socket.getInetAddress() + ":" + socket.getPort() + "的" + s);
        }

        socket.close();
        serverSocket.close();
    }
}
4.客户端发给服务器多次,服务器输出到文件
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in)); //字节输入流转换为字符输入流
        FileWriter writer = new FileWriter("e:\\b.txt",true);  //字符输出流中转换流的简化形式

        String s;
        while((s = br.readLine()) != null) {
            writer.write(s); //写入字符串s,但不包含换行符。
            writer.write(System.lineSeparator()); //System.lineSeparator()返回一个换行符的字符串
            writer.flush();
        }

        writer.close();
        socket.close();
        serverSocket.close();
    }
}

//客户端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while((s = reader.readLine()) != null) {
            byte[] bytes = s.getBytes();
            output.write(bytes);  //利用流发送数据
            output.write('\n');  //reader.Line()不读入换行符,所以要人为写入一个'\n'
        }
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
        reader.close(); // 标准输入流需要关闭,所以要调用reader.close()
    }
}

5.从文本输出到文本(文件传输)
//客户端
import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流

        BufferedReader br = new BufferedReader(new FileReader("e:\\b.txt"));
        String line;
        while((line = br.readLine()) != null) {
            output.write(line.getBytes());
            output.write('\n');
        }
        socket.shutdownOutput();  //关闭客户端的输出流,让服务器知道客户端输出完毕,此时服务器就并不会继续阻塞在InputStream的读方法那里了。
		//接收服务器的反馈。
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);

        br.close();
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
    }
}

//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in)); //封装成字符输入流
        FileWriter writer = new FileWriter("e:\\c.txt",true); // 字符输出流的简化版本
        BufferedWriter bw = new BufferedWriter(writer); //封装成缓冲字符输出流
        String line;
        while((line = br.readLine()) != null) { //该方法会一直阻塞,直到客户端的socket close或者客户端断开输出流。
            bw.write(line);
            bw.newLine();
        }
        
		//输出反馈。
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("已接收到文件".getBytes());

        bw.close();
        socket.close();
        serverSocket.close();
    }
}
6.传输图片

把字符输出输入流修改成字节输出输入流。

//客户端
import java.io.*;
import java.net.Socket;

public class Client {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1",9999); //对象创建成功即代表连接成功
        OutputStream output = socket.getOutputStream();   //获取流

        BufferedOutputStream bos = new BufferedOutputStream(output);
        FileInputStream fis = new FileInputStream("e:\\lolo.jpg");
        BufferedInputStream bis = new BufferedInputStream(fis);
        int len;
        byte[] bytes = new byte[1024];
        while((len = bis.read(bytes)) != -1) {
            bos.write(bytes,0,len);
        }
        bos.flush();
        socket.shutdownOutput();

        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);


        bufferedReader.close();
        bis.close();
        socket.close();  //只需要关闭套接字,流也会随之自动关闭
    }
}


//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9999);
        Socket socket = serverSocket.accept();
        InputStream in = socket.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(in);

        FileOutputStream fos = new FileOutputStream("e:\\copy.jpg");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int len;
        byte[] bytes = new byte[1024];
        while((len = bis.read(bytes)) != -1) {
            bos.write(bytes,0,len);
        }

        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("已接收到文件".getBytes());

        bos.close();
        outputStream.close();
        socket.close();
        serverSocket.close();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值