多线程和网络编程(网络编程)

二、网络编程

  • 网络编程入门
  • UDP通信程序
  • TCP通信程序
计算机网络

在这里插入图片描述

网络编程概述

在网络通信协议下,实现网络互连的不同计算机上运行的程序间可以进行数据交换。

网络编程三要素

在这里插入图片描述

IP地址

在这里插入图片描述

在这里插入图片描述

InetAddress的使用

在这里插入图片描述

案例:

/**
 * @Author TeaBowl
 * @Date 2021/3/26 16:46
 * @Version 1.0
 */
public class InetAddressDemo1 {
    public static void main(String[] args) throws Exception {
        //确定主机的IP地址
        //主机名称可以是机器名称或者IP地址
        //InetAddress address = InetAddress.getByName("wz");
        InetAddress address = InetAddress.getByName("192.168.142.1");

        //获取此IP地址的主机名
        String hostName = address.getHostName();

        //获得IP地址
        String hostAddress = address.getHostAddress();

        System.out.println("主机名:" + hostName);
        System.out.println("IP地址:" + hostAddress);
    }
}

控制台:

主机名:wz
IP地址:192.168.142.1

端口

在这里插入图片描述

协议

在这里插入图片描述
在这里插入图片描述

三次握手:

在这里插入图片描述


UDP通信原理

在这里插入图片描述

UDP发送数据

在这里插入图片描述

在这里插入图片描述

/**
 * @Author TeaBowl
 * @Date 2021/3/26 17:10
 * @Version 1.0
 */
public class UdpSendDemo {
    public static void main(String[] args) throws Exception {
        //创建发送端Socket对象(DatagramSocket)
        DatagramSocket socket = new DatagramSocket();

        //创建数据,打包数据
        //DatagramPacket(byte buf[],  int length,InetAddress address, int port)
        String s = "hello UDP 我来了";
        /*byte[] bys = s.getBytes();
        int len = bys.length;
        InetAddress address = InetAddress.getByName("wz");
        int port = 10099;
        DatagramPacket packet = new DatagramPacket(bys,len,address,port);*/
        DatagramPacket packet = new DatagramPacket(
                s.getBytes(),
                s.getBytes().length,
                InetAddress.getByName("wz"),
                10099);

        //调用DatagramSocket对象的send()方法发送数据
        socket.send(packet);

        //关闭发送端
        socket.close();
    }
}

UDP接收数据

在这里插入图片描述

/**
 * @Author TeaBowl
 * @Date 2021/3/26 17:29
 * @Version 1.0
 */
public class ReceiveDemo {
    public static void main(String[] args) throws Exception {
        //创建Socket对象
        DatagramSocket socket = new DatagramSocket(10099);

        //创建数据包bytes,用于接收数据
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, bytes.length);

        //接收数据
        socket.receive(packet);

        //解析数据包,把数据包里的数据data显示在控制台
        byte[] data = packet.getData();
        //int getLength():返回要发送的数据的长度或者接收到的数据的长度
        int length = packet.getLength();
        //接收到的字符串
        String s = new String(data,0,length);

        System.out.println("数据是:" + s);

        //关闭接收端
        socket.close();
    }
}

先开启接收端,再运行发送端

接收端控制台:

数据是:hello UDP 我来了                                                       

UDP通信程序练习

按照下面的要求实现程序:

  • UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束。
  • UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收。
/**
 * @Author TeaBowl
 * @Date 2021/4/3 3:22
 * @Version 1.0
 * - UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束。
 */
public class SendDemo {
    public static void main(String[] args) throws Exception {
        //创建发送端的Socket对象(DatagramSocket)
        DatagramSocket socket = new DatagramSocket();

        //自己封装键盘录入数据
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line;
        //如果输入的数据不为空
        while ((line= br.readLine())!=null){
            //如果输入的数据是886,发送数据结束
            if("886".equals(line)){
                break;
            }

            //创建数据,并把数据打包
            //输入的数据转为字节数组
            byte[] bytes = line.getBytes();
            //数据打包
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("wz"), 12345);

            //调用DatagramSocket对象的方法发送数据
            socket.send(packet);
        }
        
        //关闭发送端
        socket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 3:22
 * @Version 1.0
 * - UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收。
 */
public class ReceiveDemo {
    public static void main(String[] args) throws Exception {
        //创建发送端的Socket对象(DatagramSocket)   参数:端口号
        DatagramSocket socket = new DatagramSocket(12345);

        //死循环接收数据
        while (true){
            //创建一个数据包,用于接收数据
            byte[] bytes = new byte[1024];
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length);

            //调用DatagramSocket对象的方法接收数据
            socket.receive(packet);

            //解析数据包,并把数据在控制台显示
            //参数:接收到的数据包,0,数据长度
            System.out.println("数据是:"+new String(packet.getData(),0, packet.getLength()));
        }

        //关闭接收端
        //socket.close();
    }
}

控制台显示:

SendDemo:
hello
world
java
886

Process finished with exit code 0	出现886,发送结束了
ReceiveDemo:
数据是:hello
数据是:world
数据是:java

没结束,一直接收数据
聊天室演示(开启多个发送端):
SendDemo1:
我是1号,我爱柳岩
3号老哥牛批
886

Process finished with exit code 0		出现886,发送结束了
SendDemo2:
我是2号,我爱刘亦菲
兄弟666
886

Process finished with exit code 0		出现886,发送结束了
SendDemo3:
我是3号,我爱刘老根
哇哈哈
886

Process finished with exit code 0		出现886,发送结束了
ReceiveDemo:
数据是:我是1号,我爱柳岩
数据是:我是2号,我爱刘亦菲
数据是:我是3号,我爱刘老根
数据是:3号老哥牛批
数据是:兄弟666
数据是:哇哈哈

没结束,一直接收数据

TCP通信原理

  TCP通信协议是一种可靠的网络协议,它在通信的两端各建立了一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。

  Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。

  Java为客户端提供了Socket类,为服务器提供了ServerSocket类。

在这里插入图片描述

TCP发送数据

在这里插入图片描述

/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * TCP发送数据的步骤
 *      创建客户端的Socket对象
 *      获取输出流,写数据
 *      释放资源
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端的Socket对象
        //Socket(InetAddress address,int port):创建流套接字并将其链接到指定IP地址的指定端口号
        //Socket socket = new Socket(InetAddress.getByName("wz"), 10000);
        //Socket(String host,int port):创建流套接字并将其链接到指定IP地址的指定端口号
        Socket socket = new Socket("wz", 10000);

        //获取输出流,写数据
        //OutputStream getOutputStream():返回此套接字的输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("hello,tcp,我来了".getBytes());

        //释放资源
        socket.close();
    }
}

TCP接收数据

在这里插入图片描述

/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * TCP接受数据的步骤:
 *      创建服务器端的Socket对象(ServerSocket)
 *      获取输入流,读数据,并把数据显示在控制台
 *      释放资源
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象
        //ServerSocket(int port):创建绑定到指定端口的服务器套接字
        ServerSocket serverSocket = new ServerSocket(10000);

        //Socket accept():侦听要连接到此的套接字,并接受它
        //即:监听客户端有连接时,对应地生成一个Socket对象
        Socket accept = serverSocket.accept();

        //获取输入流,读数据,并把数据显示在控制台
        InputStream inputStream = accept.getInputStream();
        //读数据,字节数组
        //创建一个数据包,用于接收数据
        byte[] bytes = new byte[1024];
        //读取数据包长度
        int len = inputStream.read(bytes);
        //将读到的数据流,字节流转字符串
        //参数(数据包,0,长度)
        String data = new String(bytes, 0, len);
        System.out.println("数据是:" + data);

        //释放资源
        accept.close();
        serverSocket.close();
    }
}

控制台:

ServerDemo:
数据是:hello,tcp,我来了

Process finished with exit code 0

TCP通信程序练习

练习1:

  • 客户端:发送数据,接收服务器反馈
  • 服务器:接收数据,给出反馈
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:发送数据,接收服务器反馈
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端的Socket对象
        Socket socket = new Socket("wz", 10001);

        //获取输出流,写数据
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("你好啊,茉莉花茶".getBytes());

        //接收服务器反馈
        //创建输入流
        InputStream inputStream = socket.getInputStream();
        //创建数据包,用俩存放服务端的反馈
        byte[] bytes = new byte[1024];
        //获取数据包长度
        int len = inputStream.read(bytes);
        //获取数据,字节流转为字符串
        String data = new String(bytes, 0, len);
        System.out.println("客户端-接收到的-服务端反馈:" + data);

        //释放资源
        //inputStream.close();
        //outputStream.close();
        socket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收数据,给出反馈
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10001);

        //监听客户端连接,返回一个Socket对象
        Socket accept = serverSocket.accept();

        //获取输入流,读数据,并把数据显示在控制台
        InputStream inputStream = accept.getInputStream();
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        String data = new String(bytes, 0, len);
        System.out.println("服务器:" + data);

        //给客户端反馈
        OutputStream outputStream = accept.getOutputStream();
        outputStream.write("数据已经收到".getBytes());


        //释放资源
        //accept.close();
        serverSocket.close();
    }
}

控制台:

ServerDemo:
服务器:你好啊,茉莉花茶

Process finished with exit code 0
ClientDemo:
客户端:数据已经收到

Process finished with exit code 0

练习2:

  • 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
  • 服务器:接收到的数据在控制台输出
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端的Socket对象
        Socket socket = new Socket("wz", 10002);

        //键盘录入数据,直到输入886,发送数据结束
        //键盘录入的数据
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

        /**
         * 封装输出流对象
         * socket.getOutputStream()            获取字节输出流对象
         * new OutputStreamWriter(输出流对象)    输出流转为字符流对象
         * new BufferedWriter()                创建写入数据的对象
         */
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String line;
        while ((line = bufferedReader.readLine()) != null) {
            if ("886".equals(line)) {
                break;
            }

            //发送数据
            //写数据   键盘录入的数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //刷新
            bufferedWriter.flush();
        }

        //释放资源
        socket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据在控制台输出
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10002);

        //监听客户端连接
        Socket accept = serverSocket.accept();

        //获取输入流
        //字节流转为字符流,再包装为BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        String line;

        //如果读取的数据不为空,输出数据为字符串
        while ((line = bufferedReader.readLine()) != null) {
            //接收到的数据在控制台输出
            System.out.println(line);
        }

        //释放资源
        serverSocket.close();
    }
}

控制台:

ClientDemo:
hello
world
java
886

Process finished with exit code 0
ServerDemo:
hello
world
java

Process finished with exit code 0

练习3:

  • 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
  • 服务器:接收到的数据写入文本文件
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于键盘录入,直到输入的数据是886,发送数据结束
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端的Socket对象
        Socket socket = new Socket("wz", 10003);

        //键盘录入数据,直到输入886,发送数据结束
        //键盘录入的数据
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));

        /**
         * 封装输出流对象
         * socket.getOutputStream()            获取字节输出流对象
         * new OutputStreamWriter(输出流对象)    输出流转为字符流对象
         * new BufferedWriter()                创建写入数据的对象
         */
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        String line;
        while ((line = bufferedReader.readLine()) != null) {
            if ("886".equals(line)) {
                break;
            }

            //发送数据
            //写数据   键盘录入的数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //刷新
            bufferedWriter.flush();
        }

        //释放资源
        socket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据写入文本文件
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10003);

        //监听客户端连接,返回一个socket对象
        Socket accept = serverSocket.accept();

        //获取输入流
        //字节流转为字符流,再包装为BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        //将字符流写入"my\\file.txt"的操作,包装成BufferedWriter对象
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("my\\file.txt"));

        String line;
        //如果读到的数据不为空
        while ((line = bufferedReader.readLine()) != null) {
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        //释放资源
        bufferedWriter.close();
        serverSocket.close();
    }
}

控制台:

ClientDemo:
hello
java
886

Process finished with exit code 0
ServerDemo:

Process finished with exit code 0

在这里插入图片描述
练习4:

  • 客户端:数据来自于文本文件
  • 服务器:接收到的数据写入文本文件

在这里插入图片描述

/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于文本文件
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端Socket对象
        Socket socket = new Socket("wz", 10003);

        //读取文件  封装文本文件的数据,
        BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
        //发送数据  封装输出流写数据
        //OutputStreamWriter    字符流转为字节流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        //读数据,写出去
        String line;
        //readLine()    读取一行数据
        while ((line = bufferedReader.readLine()) != null) {
            //写数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //强制输出缓冲区数据
            bufferedWriter.flush();
        }

        //释放资源
        //停止读数据操作
        bufferedReader.close();
        //关闭客户端Socket对象
        socket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据写入文本文件
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10003);

        //监听客户端连接,返回一个socket对象
        Socket accept = serverSocket.accept();

        //获取输入流
        //字节流转为字符流,再包装为BufferedReader对象
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        //将字符流写入"my\\chawaner.txt"的操作,包装成BufferedWriter对象
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\chawaner.txt"));

        String line;
        //如果读到的数据不为空
        while ((line = bufferedReader.readLine()) != null) {
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        //释放资源
        bufferedWriter.close();
        serverSocket.close();
    }
}

控制台:

ServerDemo:

Process finished with exit code 0
ClientDemo:

Process finished with exit code 0

在这里插入图片描述

练习5:

  • 客户端:数据来自于文本文件,接收服务器反馈
  • 服务器:接收到的数据写入文本文件,给出反馈
  • 出现问题:程序一直等待
  • 原因:读数据的方式是阻塞式的
  • 解决办法:自定义结束标记;推荐使用shutdownOutput()方法。

不使用结束标记时,一直在等待读取数据,程序不能执行成功。

所以得使用结束标记,下面使用了”自定义结束标记“。

/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于文本文件,接收服务器反馈
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端Socket对象
        Socket socket = new Socket("wz", 10003);

        //读取文件  封装文本文件的数据,
        BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
        //发送数据  封装输出流写数据
        //OutputStreamWriter    字符流转为字节流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        //读数据,写出去
        String line;
        //readLine()    读取一行数据
        while ((line = bufferedReader.readLine()) != null) {
            //写数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //强制输出缓冲区数据
            bufferedWriter.flush();
        }

        //自定义结束标记
        bufferedWriter.write("886");
        bufferedWriter.newLine();
        bufferedWriter.flush();
        
        //接收反馈
        BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String data = bufferedReader1.readLine();
        System.out.println("服务器的反馈:" + data);

        //释放资源
        //停止读数据操作
        bufferedReader.close();
        //关闭客户端Socket对象
        socket.close();

    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据写入文本文件,给出反馈
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10003);

        //监听客户端连接,返回一个对应的Socket对象
        Socket accept = serverSocket.accept();

        //接收数据
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        //把数据写入文本文件
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\hello.txt"));

        String line;
        while ((line = bufferedReader.readLine()) != null) {//等待读取数据
            //判断结束标记
            if ("886".equals(line)){
                break;
            }
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        //给出反馈
        BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bufferedWriter1.write("文件上传成功!");
        bufferedWriter1.newLine();
        bufferedWriter1.flush();

        //释放资源
        bufferedWriter.close();
        serverSocket.close();
    }
}

控制台:

ClientDemo:
服务器的反馈:文件上传成功!

Process finished with exit code 0
ServerDemo:

Process finished with exit code 0

注意:

自定义结束标签的缺点是:如果接收到的文件里有“886”这个字段,那么就会结束文件的写入;写入的文件不包括“886”关键字之后的内容。

使用shutdownOutput和shutdownInput()结束标记方法对客户端和服务器端进行修改:

/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于文本文件,接收服务器反馈
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端Socket对象
        Socket socket = new Socket("wz", 10003);

        //读取文件  封装文本文件的数据,
        BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
        //发送数据  封装输出流写数据
        //OutputStreamWriter    字符流转为字节流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        //读数据,写出去
        String line;
        //readLine()    读取一行数据
        while ((line = bufferedReader.readLine()) != null) {
            //写数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //强制输出缓冲区数据
            bufferedWriter.flush();
        }

        //自定义结束标记
        //bufferedWriter.write("886");
        //bufferedWriter.newLine();
        //bufferedWriter.flush();

        //结束标记方法    表示输出结束
        socket.shutdownOutput();

        //接收反馈
        BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //等待读取数据
        String data = bufferedReader1.readLine();
        System.out.println("服务器的反馈:" + data);

        //释放资源
        //停止读数据操作
        bufferedReader.close();
        //关闭客户端Socket对象
        socket.close();

    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据写入文本文件,给出反馈
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10003);

        //监听客户端连接,返回一个对应的Socket对象
        Socket accept = serverSocket.accept();

        //接收数据
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
        //把数据写入文本文件
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\hello.txt"));

        String line;
        while ((line = bufferedReader.readLine()) != null) {//等待读取数据
            //判断结束标记
            //if ("886".equals(line)){
            //    break;
            //}
            bufferedWriter.write(line);
            bufferedWriter.newLine();
            bufferedWriter.flush();
        }

        //给出反馈
        BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
        bufferedWriter1.write("文件上传成功!");
        bufferedWriter1.newLine();
        bufferedWriter1.flush();

        //释放资源
        bufferedWriter.close();
        serverSocket.close();
    }
}

控制台:

ClientDemo:
服务器的反馈:文件上传成功!

Process finished with exit code 0
ServerDemo:

Process finished with exit code 0

练习6:

  • 客户端:数据来自于文本文件,接收服务器反馈
  • 服务器:接收到的数据写入文本文件,给出反馈,代码用线程封装,为每一个客户端开启一个线程
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:41
 * @Version 1.0
 * 客户端:数据来自于文本文件,接收服务器反馈
 */
public class ClientDemo {
    public static void main(String[] args) throws Exception {
        //创建客户端Socket对象
        Socket socket = new Socket("wz", 10003);

        //读取文件  封装文本文件的数据,
        BufferedReader bufferedReader = new BufferedReader(new FileReader("myThreadTest\\静夜思.txt"));
        //发送数据  封装输出流写数据
        //OutputStreamWriter    字符流转为字节流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        //读数据,写出去
        String line;
        //readLine()    读取一行数据
        while ((line = bufferedReader.readLine()) != null) {
            //写数据
            bufferedWriter.write(line);
            //换行
            bufferedWriter.newLine();
            //强制输出缓冲区数据
            bufferedWriter.flush();
        }

        //结束标记方法    表示输出结束
        socket.shutdownOutput();

        //接收反馈
        BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        //等待读取数据
        String data = bufferedReader1.readLine();
        System.out.println("服务器的反馈:" + data);

        //释放资源
        //停止读数据操作
        bufferedReader.close();
        //关闭客户端Socket对象
        socket.close();

    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/3 4:57
 * @Version 1.0
 * 服务器:接收到的数据写入文本文件,给出反馈,代码用线程封装,为每一个客户端开启一个线程
 */
public class ServerDemo {
    public static void main(String[] args) throws Exception {
        //创建服务器端的Socket对象(ServerSocket)
        ServerSocket serverSocket = new ServerSocket(10003);

        while (true){
            //监听客户端连接,返回一个对应的Socket对象
            Socket accept = serverSocket.accept();

            //为每一个客户端开启一个线程
            //ServerThread类实现Runnable接口,并重写run()方法
            new Thread(new ServerThread(accept)).start();
        }

        //服务器不关闭
        //serverSocket.close();
    }
}
/**
 * @Author TeaBowl
 * @Date 2021/4/5 14:16
 * @Version 1.0
 * ServerThread类:实现Runnable接口,并重写run()方法
 */
public class ServerThread implements Runnable {
    private Socket accept;

    public ServerThread(Socket accept) {
        this.accept = accept;
    }

    @Override
    public void run() {
        try {
            //接收数据写入到文本文件
            //接收数据
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
            //BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("myThreadTest\\Copy.txt"));

            //解决名称冲突问题
            int count=0;
            File file = new File("myThreadTest\\Copy["+count+"].txt");
            //如果文件名存在
            while (file.exists()){
                count++;
                file = new File("myThreadTest\\Copy["+count+"].txt");
            }
            //写入数据到文件
            BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));

            //读到的数据不为空时,写入数据
            String line;
            while ((line=bufferedReader.readLine())!=null){
                bufferedWriter.write(line);
                bufferedWriter.newLine();
                bufferedWriter.flush();
            }

            //给出反馈
            BufferedWriter bufferedWriter1 = new BufferedWriter(new OutputStreamWriter(accept.getOutputStream()));
            bufferedWriter1.write("文件上传成功");
            bufferedWriter1.newLine();
            bufferedWriter1.flush();

            //释放资源 关闭连接
            accept.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

控制台:

ServerDemo:

ClientDemo:
服务器的反馈:文件上传成功

Process finished with exit code 0
ClientDemo1:
服务器的反馈:文件上传成功

Process finished with exit code 0
ClientDemo2:
服务器的反馈:文件上传成功

Process finished with exit code 0

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值