java进阶打卡33

TCP通信的文件上传案例练习优化

  • 服务器端
    文件命名&循环结束&多线程提高效率
public static void main(String[] args) throws IOException {
	ServerSocket server = new ServerSocket(8888);
	
   // 让服务器一直处于监听状态(死循环accept方法):有一个客户端上传文件,就保存一个文件。 
    while(true){
    	Socket socket = server.accept();
    	
        // 使用多线程技术,提高程序的效率:有一个客户端上传文件,就开启一个线程,完成文件的上传。
        new Thread(new Runnable() {
            @Override
            public void run() {
            	try{
                	InputStream is = socket.getInputStream();
                    // 4. 判断d:\\upload文件夹是否存在,不存在则创建
                    File file = new File("d:\\upload");
                    if(!file.exists()){
                    	file.mkdirs();
                    }
                    
                    // 自定义一个文件的命名规则:防止同名的文件被覆盖。规则:域名+毫秒值+随机数
                    String fileName = "itcast" + System.currentTimeMillis() + new Random().nextInt(999999) + ".jpg";
                    FileOutputStream fos = new FileOutputStream(file + "\\" + fileName);
                    int len = 0;
                    byte[] bytes = new byte[1024];
                    while((len = is.read(bytes)) != -1){
                    	fos.write(bytes,0,len);
                    }
                    
                    socket.getOutputStream().write("上传成功".getBytes());
                    
                    fos.close();
                    socket.close();
				}catch(IOException e){
                    System.out.println(e);
                }
			}
		}).start();
	}
	
        // 服务器就不用关闭
		// server.close();
}

模拟BS版本TCP服务器

  • 分析
客户端是ie浏览器 Socket
http://127.0.0.1:8080/day11-code/web/index.html
访问服务器

服务器端 ServerSocket
读取客户端的请求信息
GET /day11-code/web/index.html HTTP/1.1
...

服务器要给客户端回写一个信息,回写一个html页面(文件)
我们需要读取index.html文件,就必须得知道这个文件的地址?
而这个地址就是请求信息的第一行中间的部分  GET /day11-code/web/index.html HTTP/1.1
可以使用BufferedReader中的方法readLine读取一行	InputStream is = socket.getInputStream();
new BufferedReader(new InputStreamReader(is));	把网络字节输入流,转为字符缓冲输入流

GET /day11-code/web/index.html HTTP/1.1
可以使用String类得方法split(" ")切割字符串,获取中间的部分
arr[1]	/day11-code/web/index.html
使用String类得方法substring(1),获取html文件的路径
day11-code/web/index.html

服务器创建一个本地的字节输入流,根据获取到的文件路径,读取html文件
【//写入HTTP协议响应头,固定写法
os.write("HTTP/1.1 200 OK\r\n".getBytes());
os.write("Content-Type:text/html\r\n".getBytes());
//必须要写入空行,否则浏览器不解析
os.write("\r\n".getBytes());】
服务器端使用网络字节输出流把读取到的文件,写到客户端(浏览器)显示
  • 代码实现
public static void main(String[] args) throws IOException {
	ServerSocket server = new ServerSocket(8080);
    Socket socket = server.accept();
    
    InputStream is = socket.getInputStream();
    // 把is网络字节输入流对象,转换为字符缓冲输入流
    BufferedReader br = new BufferedReader(new InputStreamReader(is));
    // 把客户端请求信息的第一行读取处理 GET /day11-code/web/index.html HTTP/1.1
    String line = br.readLine();
    // 把读取的信息进行切割,只要中间部分 /day11-code/web/index.html
    String[] arr = line.split(" ");
    // 把路径前边的/去掉,进行截取 day11-code/web/index.html
    String htmlpath = arr[1].substring(1);

    FileInputStream fis = new FileInputStream(htmlpath);
    OutputStream os = socket.getOutputStream();

    // 写入HTTP协议响应头,固定写法
    os.write("HTTP/1.1 200 OK\r\n".getBytes());
    os.write("Content-Type:text/html\r\n".getBytes());
    // 必须要写入空行,否则浏览器不解析
    os.write("\r\n".getBytes());
    
    int len = 0;
    byte[] bytes = new byte[1024];
    while((len = fis.read(bytes)) != -1){
    	os.write(bytes,0,len);
    }
    
    fis.close();
    socket.close();
    server.close();
}

模拟BS版本TCP服务器优化

循环结束&多线程提高效率

public static void main(String[] args) throws IOException {
	ServerSocket server = new ServerSocket(8080);

    /*浏览器解析服务器回写的html页面,页面中如果有图片,那么浏览器就会单独的开启一个线程,读取服务器的图片
      我们就得让服务器一直处于监听状态,客户端请求一次,服务器就回写一次*/    
	while(true){
        Socket socket = server.accept();
        
        new Thread(new Runnable() {
        	@Override
            public void run() {
            	try{
                	InputStream is = socket.getInputStream();
                	// 把is网络字节输入流对象,转换为字符缓冲输入流
                    BufferedReader br = new BufferedReader(new InputStreamReader(is));
                    // 把客户端请求信息的第一行读取处理 GET /day11-code/web/index.html HTTP/1.1
                    String line = br.readLine();
                    // 把读取的信息进行切割,只要中间部分 /day11-code/web/index.html
                    String[] arr = line.split(" ");
                    // 把路径前边的/去掉,进行截取 day11-code/web/index.html
                    String htmlpath = arr[1].substring(1);
                    
                    FileInputStream fis = new FileInputStream(htmlpath);
                    OutputStream os = socket.getOutputStream();

                    // 写入HTTP协议响应头,固定写法
                    os.write("HTTP/1.1 200 OK\r\n".getBytes());
                    os.write("Content-Type:text/html\r\n".getBytes());
                    // 必须要写入空行,否则浏览器不解析
                    os.write("\r\n".getBytes());

                    int len = 0;
                    byte[] bytes = new byte[1024];
                    while((len = fis.read(bytes)) != -1){
                    	os.write(bytes,0,len);
                    }

                    fis.close();
                    socket.close();
				}catch(IOException e){
                    e.printStackTrace();
                }
			}
		}).start();
	}
	
	// server.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java员工打签到代码的实现方式有很多种,以下是其中一种可能的实现方式: ```java import java.util.Date; public class Employee { private String name; private Date lastSignIn; public Employee(String name) { this.name = name; } public void signIn() { Date now = new Date(); System.out.println(name + "签到成功,时间:" + now); lastSignIn = now; } public void signOut() { Date now = new Date(); System.out.println(name + "签退成功,时间:" + now); } public void checkInStatus() { if (lastSignIn == null) { System.out.println(name + "尚未签到"); } else { System.out.println(name + "上次签到时间:" + lastSignIn); } } } ``` 上面的代码定义了一个`Employee`类,其中包含了员工的姓名和上次签到时间。类中有三个方法:`signIn()`、`signOut()`和`checkInStatus()`。`signIn()`方法表示员工签到,会打印出员工姓名和当前时间,并将当前时间记录为上次签到时间;`signOut()`方法表示员工签退,会打印出员工姓名和当前时间;`checkInStatus()`方法表示查询员工的签到状态,会打印出员工姓名和上次签到时间(如果已经签到过),否则会提示尚未签到。 如果要使用这段代码,可以在其他类中创建`Employee`对象,并调用其中的方法来完成打签到功能。例如: ```java public class Main { public static void main(String[] args) { Employee emp1 = new Employee("张三"); emp1.signIn(); emp1.checkInStatus(); emp1.signOut(); } } ``` 这段代码创建了一个名为`emp1`的`Employee`对象,姓名为“张三”。接着调用了`signIn()`方法行签到,`checkInStatus()`方法查询签到状态,最后调用了`signOut()`方法行签退。运行这段代码后,会打印出以下结果: ``` 张三签到成功,时间:Thu Jul 22 14:47:23 CST 2021 张三上次签到时间:Thu Jul 22 14:47:23 CST 2021 张三签退成功,时间:Thu Jul 22 14:47:28 CST 2021 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值