unit4 网络协议
1.协议:
软件结构:C/S(Client、Service,客户端访问) B/S(Browser、Service,浏览器访问)
网络通信协议:
TCP/IP协议:传输控制协议/因特网互联协议(transmission control protocol / Internet protocol),内部处理通信协议,采用4层分层结构
客户端向服务器发出连接请求,每次连接都要经过三次握手:
UDP协议:用户数据报协议(User Datagram Protocol),无连接通信协议,不建立通信连接
2.IP地址:电脑的唯一标识,互联网协议地址,IPv4,IPv6,查看本机地址(ipconfig),检查是否可以互联(ping 对方IP地址)
端口号:打开一个软件,OS会给此网络分配一个随机的或者特定的端口号,由2个字节组成的
80端口:网络端口 mysql:3306 oracle:1521 Tomcat:8080
4.TCP通信:
Socket类:java.net.Socket 包含了IP地址和端口号的网络单位
构造方法:Socket(String host,int port)
成员方法:OutputStream getOutputStream()返回套接字输出流
InputStream getInputStream()返回套接字输入流
void close()关闭套接字
ServerSocket类:java.net.ServerSocket
构造方法:ServerSocket(int port)
成员方法:Socket accept()侦听并接受此套接字的连接
实现步骤类似上面~~~~
TCPClient:
public static void main(String[] args) throws IOException {
//创建客户端对象Socket
Socket socket = new Socket("192.168.1.101",8888);
//获取字节输出流对象
OutputStream os = socket.getOutputStream();
//使用write方法给服务器发送数据
os.write("你好服务器".getBytes());
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
socket.close();
//error:java.net.ConnectException: Connection refused: connect
}
TCPServer:
public static void main(String[] args) throws IOException {
//创建服务器ServerSocket对象和系统要指定的端口号
ServerSocket server = new ServerSocket(8888);
//accept方法,获取socket对象
Socket socket = server.accept();
//getInputStream方法获取网络字节输入流InputStream对象
InputStream is = socket.getInputStream();
//read读取数据
byte[] bytes = new byte[1024];
int len = is.read(bytes);
System.out.println(new String(bytes,0,len));
//getOutputStream获取网络字节输出流对象
OutputStream os = socket.getOutputStream();
//write给客户端回写数据
os.write("收到谢谢".getBytes());
socket.close();
server.close();
}
ps:先运行Server端,再运行Client端,在Client显示“收到谢谢”,在Server显示“你好服务器”
例子,本地文件上传:
5.BS服务器:
客户端IE浏览器(socket)-----访问服务器(Serversocket)------读取客户端请求的内容:
访问服务器的代码:
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8080);
Socket socket = server.accept();
InputStream is = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}
}
客户端IE浏览器:
http://192.168.1.101:8080/demo22/web/index.html
读取客户端请求的内容:在控制台显示
GET /demo22/web/index.html HTTP/1.1
Host: 192.168.1.101:8080
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.81 Safari/537.36 SE 2.X MetaSr 1.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
6.函数式接口:有且只有一个抽象方法的接口
LambdaInterface:
@FunctionalInterface
//检测接口是否是函数接口,有且只有一个
LambdaImplement:
LambdaImpl implements LambdaInterface
LambdaTest:
//定义一个方法,参数使用函数式接口
public static void show(LambdaInterface li ){
li.method();
}
psvm{
//Lambda表达式,调用show方法
show(()->{
System.out.println("匿名内部类重写方法接口");
});
}
函数式接口作为方法参数:函数式接口(Runnable run)
package demo23;
public abstract class RunnableTest {
//定义一个方法startThread,参数使用函数式接口Runnable
public static void startThread(Runnable run){
//开启多线程
new Thread((java.lang.Runnable) run).start();
}
public static void main(String[] args) {
//调用方法,参数是一个接口,我们可以传递此接口的匿名内部类
startThread(new Runnable(){
@Override
public void run(){
System.out.println(Thread.currentThread().getName()
+"-->"+"线程启动了");
}
});
//调用方法,参数是一个函数式接口,我们可以传递Lambda表达式,
// 节省了匿名内部类的书写
startThread(()->{
System.out.println(Thread.currentThread().getName()
+"-->"+"线程启动了");
});
}
}
函数式接口作为方法返回值:
//排序器
public class ComparatorTest {
public static Comparator<String> getComparator(){
//方法返回值类型是一个接口(函数式接口)的时候
// 可以返回此接口的匿名内部类
return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
//按照字符串降序排序
return o2.length()-o1.length();
}
};
//也可以是:当方法返回值类型是一个函数式接口的时候,
// 我们可以返回一个Lambda表达式
// return (String o1,String o2)->{
// return o2.length()-o1.length();
// };
}
}
7.常用的函数式接口:
Supplier<T>接口:生产型接口 T get()
//方法参数传递Supplier接口,泛型使用Integer
public static int getMax(Supplier<Integer> sup){
return sup.get();
}
Consumer<T>接口:消费型接口 T accept() andThen(),组合两个接口
public static void method(String name, Consumer<String> con){
con.accept(name);
}
---------------------------------------------------------------
//定义一个方法,参数传递一个字符串和两个Consumer接口,接口泛型是字符串
public static void method
(String s, Consumer<String> con1,Consumer<String> con2){
con1.accept(s);
con2.accept(s);
//con1连接con2,先后消费执行
con1.andThen(con2).accept(s);
}
public static void main(String[] args) {
//调用method方法,传递一个字符串,两个Lambda表达式
method("hello",
(t)->{//转换成大写
System.out.println(t.toUpperCase()); },
(t)->{//转换成小写
System.out.println(t.toLowerCase()); });
}
Predicate<T>接口:判断数据类型接口 boolean test ( T t )
public static boolean checkString
(String s, Predicate<String> pre){
return pre.test(s);
}
---------------------------------------------------
String s = "sjw";
boolean b = checkString(s, (String str) -> {
return str.length() > 5;//长度是否大于5
});
System.out.println(b);
Function<T,R>接口:转换型接口
R reply(T t ),T转换为R
andThen() ,类似于Consumer里面的,先做什么后做什么,进行组合操作
public static void change(String s, Function<String ,Integer> fun){
Integer in = fun.apply(s);
//Integer改成为int时候,是自动拆箱过程
System.out.println(in);
}
------------------------------------------------
String s = "124";
change(s,(String str)->{
//把String类型转换成Integer类型
return Integer.parseInt(str);
});
unit5 Stream流
1.定义:I/O流用于读写,Stream流用于集合和数组的转化型读写
例子:集合遍历
list.stream().filter(name->name.startsWith("s"))
.filter(name->name.length()==3)
.forEach(name-> System.out.println(name));
2. 流式思想:过滤---》映射---》跳过---》计数,只有在计数count时候,模型才开始操作
元素是特定类型对象,按需计算,所以不会存储所有ALL
3.获取流:java.util.stream.Stream<T>
Map<String,String> map = new HashMap<>();
Set<String> keySet = map.keySet();//获取键
Stream<String> s3 = keySet.stream();
Collection<String> valueSet = map.values();//获取值
Stream<String> s4 = valueSet.stream();
Set<Map.Entry<String, String>> entries = map.entrySet();//获取键值对映射关系
Stream<Map.Entry<String, String>> s5 = entries.stream();
//数组转换成stream流
Stream<Integer> s6 = Stream.of(1,2,3);
//可变参数传递数组
Integer[] arr1 = {1,2,3};
Stream<Integer> s7 = Stream.of(arr1);
String[] arr2 = {"a","bb"};
Stream<String> s8 = Stream.of(arr2);
4.流的常用方法:
//forEach方法,遍历流的数据,是终结方法,遍历后不能调用其他的方法了
Stream<String> stream = Stream.of("sjw", "only");//获取流
stream.forEach((String name)->{
System.out.println(name);
});//foeEach方法进行遍历
//stream.forEach((name)->{sout(name)}); 同理的
-----------------------------------------------------
//filter方法过滤
Stream<String> stream1 = Stream.of("林子", "爽");//获取流
stream1.filter((String name)->{
return name.startsWith("林");
});//filter元素过滤
stream1.forEach((name)->{
System.out.println(name);});
//error:stream has already been operated upon or closed
//stream是管道流,只可以被消费一次
映射方法map:转换数据类型,类似于apply()
Stream<String> stream = Stream.of("11", "22");//获取流
Stream<Integer> stream1 = stream.map((String s) -> {
return Integer.parseInt(s);
});//map方法,将string转换成integer
stream1.forEach(i-> System.out.println(i));//遍历
统计个数方法count:返回long类型,终结方法
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
Stream<Integer> stream2 = list.stream();//数组转换成stream流
System.out.println(stream2.count());
取用前n个方法limit:截取方法,long类型整数,延迟方法可以调用其他方法
Stream<String> stream3 = Stream.of("11", "22");//获取流
Stream<String> stream4 = stream3.limit(2);
stream4.forEach(name-> System.out.println(name));
跳过前几个方法skip:
tream<String> stream5 = Stream.of("11", "22");//获取流
Stream<String> stream6 = stream5.skip(1);//跳过
stream6.forEach(name-> System.out.println(name));
组合方法concat:参数传递两个流合并成为一个流,静态方法
Stream<String> stream1 = Stream.of("11", "22","33");//获取流
Stream<String> stream2 = Stream.of("sjw", "linzi","shuang");//获取流
Stream<String> stream3 = Stream.concat(stream1,stream2);//合并
stream3.forEach(name-> System.out.println(name));