Java29Tcp,文件上传/UUID,Junit

Posted 码农编程录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java29Tcp,文件上传/UUID,Junit相关的知识,希望对你有一定的参考价值。


1.Tcp单向通讯:" ".getBytes()

端游将页游好处和坏处相反。一个字节是2的8次方即256,所以0-255。ipv4组合方式共2的32(4*8=32个空格)次方即43亿个。
在这里插入图片描述
ip相当于小区,port相当于门牌号。
在这里插入图片描述
下面将三要素融合,https中s就是secure。
在这里插入图片描述
socket封装了io流,所以要关。高层socket关了,低层也会关。
在这里插入图片描述

package com.itheima01.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws IOException {        
        String host = "127.0.0.1"; //1.连接服务端(指定服务端的ip和port)自动连接
        int port = 10010;
        Socket socket = new Socket(host, port);
       
        OutputStream os = socket.getOutputStream();  //2.写出数据
        os.write(" hello, tcp".getBytes());
        socket.close();
    }
}
package com.itheima01.tcp;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10010); //1.创建服务端Socket对象,并指定port。ip是路由器分配的
        System.out.println("1");        
        Socket socket = serverSocket.accept(); //2.获取客户端的连接(阻塞方法)
        System.out.println("2");
        
        InputStream is = socket.getInputStream(); //3.假设接收到客户端连接 : 服务端读取数据        
        int length = -1;
        byte[] buffer = new byte[1024];
        while((length = is.read(buffer)) != -1){
            String msg = new String(buffer, 0, length);
            System.out.println("收到客户端的数据:" + msg);
        }
        socket.close();//关闭和客户端的连接
        serverSocket.close(); // 关闭服务端
    }
}

2.Tcp双向通讯:socket中介

package com.itheima02.doubled;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
//准备,写,读
public class TcpClient {
    public static void main(String[] args) throws IOException {
        String host = "127.0.0.1";  //1.连接服务端 (指定服务端的ip和port) 自动连接
        int port = 10010;
        Socket socket = new Socket(host, port);

//11111111111111111111111111111111111111111111111111111111111111111111111  
        OutputStream os = socket.getOutputStream(); //2.写出数据
        os.write(" hello, tcp".getBytes());                
        socket.shutdownOutput(); //解决: 告知对方 写完了        

//1111111111111111111111111111111111111111111111111111111111111111111111 
        InputStream is = socket.getInputStream(); //3.客户端收到数据        
        int length=-1;
        byte[] buffer = new byte[1024];
        while((length = is.read(buffer)) != -1){
            String msg = new String(buffer, 0, length);
            System.out.println("收到服务端的数据:" + msg);
        }
        socket.close();
    }
}
package com.itheima02.doubled;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10010); //1.创建服务端Socket对象,并指定port
        System.out.println("1");
        Socket socket = serverSocket.accept(); //2.获取客户端的连接(阻塞方法)
        System.out.println("2");

//111111111111111111111111111111111111111111111111111111111111111111111111111111111        
        InputStream is = socket.getInputStream(); //3.假设接收到客户端连接 : 服务端读取数据
        int length = -1;
        byte[] buffer = new byte[1024];
        /*
        *   问题: read方法是一个阻塞方法
        *       以前: 读文件,读到末尾返回-1
        *       现在: 读socket中传输的数据 (像电话), 对方socket关掉就算是末尾了
        * 
        *   解决: 1. 对方在输出结束,可以直接关闭socket,这个数据就结束了,但是对方就不能再接收了
        *        2. 对方直接告知已经输出结束,socket不需要关
        */
        while((length = is.read(buffer)) != -1){//客户端socket.shutdownOutput();服务端就不会阻塞在这一行
            String msg = new String(buffer, 0, length);
            System.out.println("收到客户端的数据:" + msg);
        }  

//111111111111111111111111111111111111111111111111111111111111111111111111111111111111      
        OutputStream os = socket.getOutputStream(); //4.服务端写出数据  
        os.write(" 好,退下吧~~".getBytes()); 
        socket.close();//关闭和客户端的连接  //这里socket.shutdownOutput();可以不写,因为直接close了
        serverSocket.close(); // 关闭服务端
    }
}

3.案例_文件上传:serverSocket

在这里插入图片描述

package com.itheima03.upload;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class UploadClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10086);

//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
        FileInputStream fis = new FileInputStream("柳岩.jpg");//读本地文件(da14模块下有个柳岩.jpg),写到服务器socket中        
        OutputStream os = socket.getOutputStream();    
                             
        int length = -1;
        byte[] buffer = new byte[1024];
        while((length = fis.read(buffer)) != -1){ //读
            os.write(buffer,0,length); //写
        }
        fis.close();
        socket.close();
    }
}
package com.itheima03.upload;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10086);
        Socket socket = serverSocket.accept();	

//1111111111111111111111111111111111111111111111111111111111111111111111111111111	
        InputStream is = socket.getInputStream();         
        long time = System.currentTimeMillis();//系统当前时间毫秒值
        FileOutputStream fos = new FileOutputStream("c:/test/server/" + time + ".jpg");    
             
        int length = -1;
        byte[] buffer = new byte[1024];
        while((length = is.read(buffer)) != -1){ //读
            fos.write(buffer,0,length);  //写
        }
        fos.close();
        socket.close();
        serverSocket.close();
    }
}

4.多线程优化服务端与UUID:is和fos

package com.itheima04.good;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;
/*
* 优化: 1. 服务器一般是24小时不关闭的,前面写的只能收到一张图片服务器就关闭了
*         解决: 1. 死循环
*                   java.net.BindException: Address already in use: JVM_Bind。绑定异常(port重复占用)
*                   解决: 代码加在accept接收客户端请求之前。但是现象: 同一时间只能处理一个请求,单线程
* 
*               2. 想支持多个客户端的并发访问
*                   解决: 引入多线程  代码加在阻塞之后
*                   补充: 线程池 管理 线程(1. 避免线程频繁创建和销毁 2. 控制线程数量)
* 
*       2. 文件名 : 以系统当前时间命名(并发: 同一毫秒,有两个用户同时上传文件, 就会有用户文件覆盖)
*               1. 一般文件,不需要标识这个图片属于谁的 : 服务器用UUID                             
*               2. 文件名需要跟用户上传的文件名一致 : 需要另一个线程传输这个文件名(这个用户id + 文件名)
*/
public class UploadServer {
    public static void main(String[] args) throws IOException {        
        ServerSocket serverSocket = new ServerSocket(10086); //只创建一个服务端,一个端口不能被两个程序占用,不能在这行上面加while(true)
        while(true){  //死循环接收客户端请求            
            Socket socket = serverSocket.accept(); //虽然while(true),但这行会阻塞
            //有客户上门才开线程,不能无限开。
            new Thread(new Runnable() { //不能放accept()前面,不能无限开线程
                @Override
                public void run() {
                    try {
                        InputStream is = socket.getInputStream();                        
                        // long time = System.currentTimeMillis();//系统当前时间毫秒值
                        String name = UUID.randomUUID().toString().replace("-", ""); //下行time改为name
                        FileOutputStream fos = new FileOutputStream("c:/test/server/" + name + ".jpg");
                        
                        int length = -1;
                        byte[] buffer = new byte[1024];
                        while((length = is.read(buffer)) != -1){
                            fos.write(buffer,0,length);
                        }                        
                        fos.close(); //应该放在finally中
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
//         serverSocket.close(); // 服务器不能关闭,关了就不回到while(true)了
        }
    }
}
package com.itheima04.good;
import java.util.UUID;
// UUID: 通用唯一标识符(Universally Unique Identifier),永不重复
public class UuidDemo {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
//            UUID uuid = UUID.randomUUID();
//            String str = uuid.toString().replace("-", ""); 
            String str = UUID.randomUUID().toString().replace("-", ""); //这行同上两行
            System.out.println(str);
        }
    }
}

如下未把UUID的 - 替换为空。
在这里插入图片描述
如下BS案例:socket被写,页面被读。
在这里插入图片描述

package com.itheima05.bs;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class BsServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10090);
        Socket socket = serverSocket.accept();
        
//1111111111111111111111111111111111111111111111111111111111111111111111111111
        OutputStream os = socket.getOutputStream(); //写出页面
        os.write("HTTP/1.1 200 OK\\r\\n".getBytes()); // http协议的响应行  第一行
        os.write("Content-Type:text/html\\r\\n\\r\\n".getBytes()); //http协议的响应头 第二行,第三行为空白
        FileInputStream fis = new FileInputStream("index.html"); //已有,用来被读

        int length = -1;
        byte[] buffer = new byte[1024];
        while((length = fis.read(buffer)) != -1){
            os.write(buffer,0,length);
        }
        fis.close();
        socket.close();
        serverSocket.close();
    }
}

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

5.Junit测试框架:手动加jar包

在这里插入图片描述

package com.itheima01.junit;
import org.junit.Test;
/*
*   使用Junit测试框架:1. 写一个方法,在方法声明上加上 注解 @Test
*       2. 导库 : jar包 (java archive : java档案包 ) -> 很多.class文件的压缩包
*          JDK : JVM + 很多jar包(开发者使用sun公司的很多类)
*          idea开发工具自动集成了 junit测试框架的jar包
*/
public class JunitDemo {
 /*   public static void main(String[] args) { //不用再写main方法了
        int i = 1/0;
        System.out.println(i);
    }*/
    @Test
    public void method01(){ 
        int i = 1/0;
        System.out.println(i); //出现异常,jvm要创建异常,打印异常信息io耗时
    }
} 

如下必须要文件类名和public class类名保持一致,一个类即一个文件。
在这里插入图片描述
如上若失效解决:在工程目录下建一个与src并列的包test,并且右击test文件夹Mark Director as为Test Sources Root。File -> Project Structure->Modules再如下。
在这里插入图片描述

package com.itheima01.junit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.FileInputStream;
/*
*  Junit测试框架的使用规范
*       1. 写一个方法,在方法声明上加上 注解 @Test (如果当前项目没有集成Junit jar包, 需集成)
*       2. 方法声明
*               public void 方法名(空){  //里面必须为空
*                   要测试的代码
*               }
*       3. 使用:1. 把鼠标放在方法内, 可以使当前方法运行
*               2. 鼠标放在类中方法外, 可以使类中所有测试方法运行
*       4. 注解上:1. @Test : 核心注解
*                 2. @Before :  在每一个@Test注解之前都会运行(用在资源初始化上,可以少写代码)
*                 3. @After :  在每一个@Test注解之后都会运行(用在资源释放上)
*/
public class JunitDemo02 {
    FileInputStream fis;
    @Before
    public void method00(){
        System.out.println("在每个Test之前"); //注意 每个
    }
    @After
    public void method11(){
        System.out.println("在每个Test之后");
    }
    @Test
    public void method01(){
        System.out.println("xx");
    }
    @Test
    public void method02()Java工具类:生成UUID

关于请问如何用java生成一个指定长度的UUID

TCP 上传文件

文件上传uuid给上传的文件随机重命名

java===TCP(文件上传功能)

java 生成UUID重复