学习笔记day01——IO流和用TCP传输数据等

day01、I/O流

I:input 输入(读取)

O:output 输出(写入)

流:数据(字符,字节)1个字符=2个字节=8个二进制位

  • 输入:把硬盘中的数据读取到内存中使用
  • 输出:把内存中的数据写入到硬盘中保存
  java.io.OutputStream:字节输出流

*           此抽象类是输出字节流的所有类的父类超类
*           定义了一些成员方法
*           public void close():关闭此输出流并释放与此流相关联的任何系统资源。
*           public void flush():刷新此输出流并强制任何缓冲的输出字节被写出。
 *           public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
 *           重点      public void write(byte[] b, int off, int len) :从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。

具体使用I\O

客户端

1.连接服务器Socket

2.发送消息

//客户端
public class TcpClientDemo01 {
    public static void main(String[] args) {
        Socket socket=null;
        OutputStream os=null;
        try {//1.要知道服务器的地址2.端口号
            InetAddress serverIP = InetAddress.getByName("127.0.0.1");
            int port = 9999;
            //2.创建一个socket连接
            socket = new Socket(serverIP,port);
            //3.发送消息IO流
             os = socket.getOutputStream();
            os.write("nihao".getBytes());//通知是一个Byts的类型
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

服务器

1.建立服务的端口 ServletSocket

2.等待用户的连接 accept

3.接受用户的消息

//服务端
public class TcpServerDemo01 {
    public static void main(String[] args) {
        ServerSocket serverSocket=null;
        Socket socket = null;
        InputStream is=null;
        ByteArrayOutputStream Baos=null;
        try {//1.我得有一个地址
           serverSocket = new ServerSocket(9999);
            //2.等待客户端连接过来
            socket = serverSocket.accept();//这个socket和Client中的Socket是一个对象可以获取到客户端的响应
            //3.读取客户端的消息 也就是读取socket中的消息
            is = socket.getInputStream();
            //管道流
            Baos = new ByteArrayOutputStream();//将客户端的数据流和服务器端的客户流用一个管道包裹起来实现IO流的数据交换
            //创建缓冲区new byte[1024]创建一个长度为1024字节长的缓冲区来存放
            byte[] buffer = new byte[1024];
            int len;
            while((len=is.read(buffer))!=-1){
                Baos.write(buffer,0,len);//利用管道流将存储的数据输出出来 返回的类型是byte[]数组
            }
            System.out.println(Baos.toString());//将Baos中的byte[]数组转换为String类型

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关闭资源流先进后关,后进先关
            if(Baos!=null){
            try {
                Baos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
            if(is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(serverSocket!=null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

深入理解难点重点

 //创建缓冲区new byte[1024]创建一个长度为1024字节长的缓冲区来存放
            byte[] buffer = new byte[1024];
            int len;
            while((len=is.read(buffer))!=-1){
                Baos.write(buffer,0,len);//利用管道流将存储的数据输出出来 返回的类型是byte[]数组
            }
            System.out.println(Baos.toString());//将Baos中的byte[]数组转换为String类
    
    

(len=is.read(buffer))!=-1 如何理解
is.read()是一个字节一个字节的读取is中的数据
而用buffer就可以将这些字节分为块来传输 如果数据有10000字节 那么就会分为10000/1000 + 1 =11个
为什么要+1呢:
流程
若我们下载一个文件,要在读取中不断的获取read()的返回值,判断何时-1,来表示读取完成。
read(buffer)如何读入?
如10000byte的文件下载,我们buffer长度1000,read(buffer)其实可以看做,是将文件分成【(10000除以1000 向上取整)+1 份】11份,其中最后一块其实就是个空的,用来判断文件读取完成。

传输文件

客户端

package com.you.lesson2;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

//接受文件
public class TcpServerDemo02 {
    public static void main(String[] args) throws IOException {
        //1.创建服务(端口)
        ServerSocket serverSocket = new ServerSocket(9000);
        //2.监听客户端的连接
        Socket socket = serverSocket.accept();//阻塞式监听,一直会监听,客户端连接后停止
        //3.获取数据流
        InputStream is = socket.getInputStream();
        //但是获取的数据是数据流最终要获取到一个文件 所以要把这个数据流输出成文件
        FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
        //设置缓冲区输出文件 重点反复理解
        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){//重点 反复理解
            fos.write(buffer,0,len);
        }
        //数据接受完毕之后给客户端一个响应 我好了
        OutputStream os = socket.getOutputStream();
        os.write("我好了你可以断开了".getBytes());
        //断开连接
        fos.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

重难点理解

 //3.获取数据流
        InputStream is = socket.getInputStream();
        //但是获取的数据是数据流最终要获取到一个文件 所以要把这个数据流输出成文件
		FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));

这里用socket获取到了客户端传来的数据流

但是最终要获得的是一个文件而不是数据流

所以使用了new FileOutputStream()这样的一个管道流把数据流转换成文件也就是后面括号中的内容

//设置缓冲区输出文件 重点反复理解
        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){//重点 反复理解
            fos.write(buffer,0,len);
        }

这里while循环体中为什么用fos而不是is

因为最终输出出来的只能是文件

在有管道层fos在 is就不能掉用write方法

只有fos可以调用

客户端

package com.you.lesson2;

import java.io.*;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;

//文件传输客户端
public class TcpClientDemo02 {
    public static void main(String[] args) throws IOException {
        //1.获取ip地址
//        InetAddress Inet = new InetAddress.getByName("127.0.0.1"); 会爆红错 待解决
        //1.升级版直接建立socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
        //2.创建一个输出流
        OutputStream os = socket.getOutputStream();
        //3.获得文件流
//        先读取文件再把文件变成一个流再写出去
        FileInputStream fls = new FileInputStream(new File("QQ截图20200405185041.png"));
        //4.写出文件(设置一个缓冲区先把文件流保存起来再通过os写出去) 重点反复理解
        byte[] buffer = new byte[1024];//设置缓冲区大小
        int len;
        while((len=fls.read(buffer))!=-1){
                os.write(buffer,0,len);
        }
        //通知服务器 我已经发送完了
        socket.shutdownOutput();//socket.shutdownOutput方法是关闭发送的信号 告诉服务器端已经传输完了
        //确定服务器接受完事儿,关闭资源
        InputStream is = socket.getInputStream();
        //传过来的是一个Byte[]数组 所以我们用new 一个Byte数组来输出
        ByteArrayOutputStream Baos = new ByteArrayOutputStream();
        byte[] bufffer = new byte[1024];
        int len2;
        while ((len2=is.read(buffer))!=-1){
            Baos.write(buffer,0,len2);
        }
        System.out.println(Baos.toString());
        //5.关闭资源
        Baos.close();
        is.close();
        fls.close();
        os.close();
        socket.close();
    }
}
//1.获取ip地址
//        InetAddress Inet = new InetAddress.getByName("127.0.0.1"); 会爆红错 待解决
        //1.升级版直接建立socket连接
        Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);

升级版的建立socket连接。

今天IO学习心得

三次握手,4次挥手
  • 三次握手:

    • A:我要传送数据了
    • B:好了我知道你要传送了
    • A:传送
  • 四次挥手:

    • A:我要结束了

    • B:我知道你要结束了

    • B:你真的要断开了吗

    • A:我真的要断开了

TCP传输数据的流程
客户端和服务端

客户端:

1.获取服务器的ip地址和端口 new InenAddress 升级版:new Socket(InetAddress.getByName(“127.0.0.1”), 9000)

2.获取数据流

2.1 直接发送信息

socket.GetOutputStream();//直接发送一个数据流 
//						   直接用os.write("xxx".GetByte[])发送信息

2.2 发送其他类型(文件等。。。)的信息

socket.InputStream();//先要获取文件的信息
//文件:
//3.获得文件流
//        先读取文件再把文件变成一个流再写出去
        FileInputStream fls = new FileInputStream(new File("QQ截图20200405185041.png"));
        //4.写出文件(设置一个缓冲区先把文件流保存起来再通过os写出去) 重点反复理解  
		//看最终需要的是什么 是字符就用os.write
        byte[] buffer = new byte[1024];//设置缓冲区大小
        int len;
        while((len=fls.read(buffer))!=-1){
                os.write(buffer,0,len);
        }

3.将数据流转换成相应的类型(Byte[]数组,文件。。。。)

字节流:直接用os.write("xxx".GetByte[])//这一步也是将String类型的xxx转换为Byte[]类型的字节数组
    
文件:
FileInputStream fls = new FileInputStream(new File("QQ截图20200405185041.png")); 
//new File将文件转化为FileInputString文件

4.关闭资源

原则 先开后关,后开先关

服务器端:

1.设定服务器的端口

ServerSocket serverSocket = new ServerSocket(9000); //new ServerSocket

2.获取客户端中的响应

 Socket socket = serverSocket.accept();//serverSocker.accept()

3.与客户端类似但是相反的获取数据流

3.1 直接接受信息

socket.InputStream();//获取的数据要通过转码
ByteArrayOutputStream Baos = new ByteArrayOutputStream();//总之接受的一方需要设置一个管道层来转换

3.2 接受其他类型(文件等。。。)的信息

 FileOutputStream fos = new FileOutputStream(new File("receive.jpg"));
        //设置缓冲区输出文件 重点反复理解
        byte[] buffer = new byte[1024];
        int len;
        while ((len=is.read(buffer))!=-1){//重点 反复理解
            fos.write(buffer,0,len);//最终需要的是文件所以用fos.write
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值