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