zoukankan      html  css  js  c++  java
  • JAVA学习day11

    网络编程

    6.TCP

    len = is.read(buffer)) != -1的原理详解
    客户端

    1. 连接服务器Socket
    2. 发送消息

    服务器

    1. 建立服务的端口 ServerSocket
    2. 等待用户的链接 accept
    3. 接收用的消息

    实现聊天

    TcpClientDemo01

    //客户端
    public class TcpClientDemo01 {
        public static void main(String[] args) {
            Socket socket = null;
            OutputStream os = null;
    
            try {
                //1.要知道服务器的地址、端口号
                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("你好".getBytes());
    
    
    
            } 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();
                    }
                }
            }
    
        }
    }
    
    

    TcpServerDemo01

    //服务端
    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);
                //没有while只监听一次,有while(true)一直监听
                while (true) {
                    //2.等待客户端链接过来
                    //此处socket等于Client中的socket,已经建立连接后就是同一个
                    socket = serverSocket.accept();
                    //3.读取客户端信息
                    is = socket.getInputStream();
    
    
                    //管道流
                    baos = new ByteArrayOutputStream();
                    byte[] buffer = new byte[1024];
                    int len;
                    while((len=is.read(buffer))!=-1){
                        baos.write(buffer,0,len);
                    }
    
                    System.out.println(baos.toString());
                }
    
                /*
                byte[] buffer = new byte[1024];
                int len;
                //样板代码,此处read直接读到buffer最后,len直接为数组长度,如果用if输出是一样的结果
                while ((len=is.read(buffer))!=1){
                    String msg = new String(buffer,0,len);
                    System.out.println(msg);
                }
                 */
    
    
    
    
            } 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();
                    }
                }
    
    
            }
    
    
        }
    
    
    }
    
    

    运行结果(运行两次Client):
    你好
    你好

    注释掉的代码:如果字节流断了会变成乱码,真正采用的是管道流。
    缓冲流管道流
    此处用的是装饰者模式,目的是在不创造更多子类的情况下,将对象的功能加以扩展。此处就是调用toString()对象。

    文件上传

    TestClientDemo02

    public class TcpClientDemo02 {
        public static void main(String[] args) throws IOException {
            //1. 创建一个socket链接
            Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 9000);
            //2. 创建一个输出流
            OutputStream os = socket.getOutputStream();
            //3. 读取文件
            FileInputStream fis = new FileInputStream("2_1.jpg");
            //4. 写出文件
            byte[] buffer = new byte[1024];
            int len;
            while ((len=fis.read(buffer))!=-1){
                os.write(buffer,0,len);
            }
            //通知服务器,我已经结束了
            socket.shutdownOutput();//我已经传输完了!
    
            //确定服务器接收完毕才断开连接
            InputStream inputStream = socket.getInputStream();
            //String byte[]
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
            byte[] buffer2 = new byte[1024];
            int len2;
            while((len2=inputStream.read(buffer2))!=-1){
                baos.write(buffer2,0,len2);
            }
            System.out.println(baos.toString());
    
    
            //5.关闭资源
            fis.close();
            os.close();
            socket.close();
    
        }
    }
    
    

    TestServerDemo02

    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();
            //4.文件输出
            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 outputStream = socket.getOutputStream();
            outputStream.write("我接收完毕了,你可以断开了".getBytes());
    
            //关闭资源
    
            fos.close();
            is.close();
            socket.close();
            serverSocket.close();
        }
    }
    
    

    在TestClientDemo02中,需要在中间加入socket.shutdownOutput();因为上面的代码在往服务器端进行输出,而服务器端并不知道有没有接受完输入,所以不会告诉客户端接收完毕,而客户端又在等待服务器端告诉客户端已经接收完毕,所以代码不会继续运行。而Demo01里双方都是直接关闭流和链接,所以不用shutdown也会结束。

  • 相关阅读:
    node环境下安装vue-cli
    Git 查看、删除、重命名远程分支
    git 错误 fatal: Not a valid object name: 'master'.
    爬虫基本原理
    最长非重复子串(python实现)
    数据分析初步(jupyter常用快捷键,numpy,pandas,matplotlib常用用法)
    学linux,这篇就够了
    爬虫之requests
    nginx配置
    Linux下uwsgi服务器配置及重启
  • 原文地址:https://www.cnblogs.com/ebym/p/15705855.html
Copyright © 2011-2022 走看看