释放资源
接收数据的步骤
数据键盘录入+接收生成文本文件练习
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket('192.168.31.77',10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
if ('886'.equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println('客户端:'+data);
}
s.close();
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
// InputStream is = s.getInputStream();
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter('untitled1copy.txt'));
String line;
while((line = br.readLine())!=null){
System.out.println('服务器:'+line);
bw.write(line);
bw.newLine();
bw.flush();
//给出反馈
OutputStream os = s.getOutputStream();
os.write('收到'.getBytes());
}
ss.close();
bw.close();
}
}
所需类型不同
接口组成更新概述
释放资源
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len;
while ((len = is.read(bys))!=-1){
String data = new String(bys,0,len);
System.out.println(data);
}
s.close();
ss.close();
}
接口中私有方法的定义格式:
范例:publicstaticvoidshow(){}
推到与省略
public可以省略,default不能省略
静态方法
TCP发送数据
范例:publicdefaultvoidshow3(){}
public可以省略,static不能省略
如果方法的返回值是一个函数式接口,我们可以使用Lambda表达式作为返回结果
如果参数有且仅有一个,那么小括号可以省略
接口中静态方法的注意事项:
Socketaccept()侦听要连接到此套接字并接受它。
Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候自动生成
UDP发送数据
创建服务器端的Socket对象
接口的组成
::该符号为引用运算符,而它所在的表达式被称为方法引用
范例:Student::new
public interface StudentBuilder {
Student build(String name,int age);
}
public class StudentDemo {
public static void main(String[] args) {
// useStudentBuilder((name,age)->{
// return new Student(name,age);
// });
useStudentBuilder(((name, age) -> new Student(name,age)));
//引用构造器
useStudentBuilder(Student::new);
}
private static void useStudentBuilder(StudentBuilder s) {
Student sm = s.build('xiaohuang', 30);
System.out.println(sm.getName()+','+sm.getAge());
}
}
TCP通信程序练习
public static void main(String[] args) throws IOException {
// Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
// Socket s = new Socket(Inet4Address.getByName('m'),10086);
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
Socket s = new Socket('m',10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write('hello'.getBytes());
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println('客户端:'+data);
// int len;
// while ((len = is.read(bys))!=-1){
// String data = new String(bys,0,len);
// System.out.println('客户端:'+data);
// }
s.close();
os.close();
is.close();
}
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println('服务器:'+data);
// int len;
// while ((len = is.read(bys))!=-1){
// String data = new String(bys,0,len);
// System.out.println('服务器:'+data);
// }
//给出反馈
OutputStream os = s.getOutputStream();
os.write('收到'.getBytes());
s.close();
ss.close();
os.close();
}
创建发送端的Socket对象
调用DatagramSocket对象的方法发送数据
格式:类名::静态方法
省略规则:
如果方法的参数是一个函数式接口,我们可以使用Lambda表达式作为参数传递
出现程序一直等待的问题,
Function
defaultConsumer
创建客户端的Socket对象
Interger类的方法:publicstaticintparseInt(Strin转换为int类型数据
public static void main(String[] args) {
useConverter(s-> Integer.parseInt(s)
);
useConverter(Integer::parseInt);
}
private static void useConverter(Converter c) {
int cn = c.convert('9999');
System.out.println(cn);
}
InputStreamgetInputStream()返回此套接字的输入流。
创建数据,并把数据打包
函数式接口作为方法的参数
方法引用符
根据调用方法的参数得知Lambda对应的接口:newThread(()->Systeout.println('Lambda')).start();
Runnable r =()-> System.out.println('Lambda表达式');
new Thread(r).start();
new Thread(()->System.out.println('Lambda')).start();
创建接收端的Socket对象
方法引用
public static void main(String[] args) {
useInter(s->{
System.out.println(s);
});
//方法引用符::
useInter(System.out::println);
//可推导的就是可省略的
}
Lambda表达式被类方法替代的时候,他的形式参数全部传递给静态方法作为参数
根据局部变量的赋值得知Lambda对应的接口:Runnabler=()->Systeout.println('Lambda表达式');
ServerSocket(intport)创建绑定到指定端口的服务器套接字。
使用限制不同
UDP通信程序练习
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
while (true){
DatagramSocket ds = new DatagramSocket(10086);
//DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//void receive(DatagramPacket p) 从此套接字接收数据报包。
ds.receive(dp);
System.out.println(new String(dp.getData(),0,dp.getLength()));
ds.close();
}
}
}
public class Demo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
//自己封装键盘录入数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = br.readLine())!=null){
if ('886'.equals(line)){
break;
}
byte[] bys = line.getBytes();
DatagramPacket dp = new DatagramPacket(bys,bys.length,Inet4Address.getByName('m'),10086);
//发送数据报包
ds.send(dp);
}
ds.close();
}
}
Lambda表达式被对象的实例方法替代的时候,它的形参全部传递给该方法作为参数
Lambda表达式练习
基于UDP协议的通信双方,没有所谓的客户端和服务器概念
Supplier
public static void main(String[] args) {
String s = getString(() -> 'xiaobai');
System.out.println(s);
}
private static String getString(Supplier sup){
return sup.get();
}
Predicate
public static void main(String[] args) {
boolean b = chechString('hellojava', s -> s.length() > 8);
System.out.println(b);
boolean b1 = checkString('helloworld', s -> s.length() > 8, s -> s.length() < 16);
System.out.println(b1);
}
private static boolean chechString(String s , Predicate p){
return p.negate().test(s);
}
private static boolean checkString(String s, Predicate p1, Predicate p2){
// return p1.test(s)&&p2.test(s);
return p1.and(p2).test(s);
}
@FunctionalInterface放在接口定义的上方,如果接口是函数式接口,编译通过,如果不是,编译失败
voidclose();
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket(10086);
//DatagramPacket(byte[] buf, int length) 构造一个 DatagramPacket用于接收长度为 length数据包。
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys,bys.length);
//void receive(DatagramPacket p) 从此套接字接收数据报包。
ds.receive(dp);
//byte[] getData() 返回数据缓冲区。
// byte[] data = dp.getData();
//int getLength() 返回要发送的数据的长度或接收到的数据的长度。
// int len = dp.getLength();
// String dataString = new String(data,0,len);
// System.out.println(dataString);
System.out.println(new String(dp.getData(),0,dp.getLength()));
ds.close();
}
}
参数类型可以省略,但是有多个参数的情况下,不能只省略一个
范例privatestaticvoidmethod(){}(静态方法只能调用静态方法)
获取输出流,写数据
引用对象的实例方法
实现原理不同
UDP接收数据
该方法不需要参数,它会按照某种实现逻辑返回一个数据
关闭接收端
接口中的静态方法
defaultPredicate
booleantest(Tt):对给定的参数进行判断,返回一个布尔值
OutputStreamgetOutputStream()返回此套接字的输出流。
Lambda表达式
调用DatagramSocket对象的方法接收数据
代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
Supplier
静态方法只能调用私有的静态方法
格式:publicdefault返回值类型方法名{}
接口组成更新
默认方法
解析数据包,并把数据在控制台显示
Lambda表达式:只能是接口
接口中默认方法的定义格式:
默认方法可以调用私有方法的静态方法和非静态方法
格式:类名::new
抽象方法:publicabstract
Socket(Stringhost,intport)创建流套接字并将其连接到指定主机上的指定端口号。
引用构造器
DatagramPacket(byte[]buf,intlengt构造一个DatagramPacket用于接收长度为length数据包
私有方法
形式参数:如果有多个参数,参数之间用逗号隔开:如果没有参数,留空即可
格式private返回值类名方法名(参数列表){}
格式:对象::成员方法
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象,从而在通信的两端形成网络虚拟链路,一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信
格式:(形式参数)—>{代码块}
Tget();获得结果
接口中的私有方法
必须有上下文环境,才能推导出Lambda对应的接口
Predicate
接口中静态方法的定义格式:
Lanbda表达式的省略模式
Rapply(Tt):将此函数应用于给定的参数
格式:类名::成员方法
startThread(()->Systeout.println(ThrascurrentThread().getName()+'线程启动'));
函数式接口:有且仅有一个抽象方法的接口
@FunctionalInterface
public interface MyInterface {
void show();
}
public class MyInterfaceDemo {
public static void main(String[] args) {
MyInterface my = ()-> System.out.println('函数式接口');
my.show();
}
}
TCP通信原理
常用的函数式接口
voidreceive(DatagramPacketp)从此套接字接收数据报包
Lambda表达式被类的实例方法代替的时候,第一个参数作为调用者,后面的参数全部传递给该方法作为参数
获取输入流,读数据,并把数据显示在控制台
Java提供DatagramSocket类最为基于UDP协议的Socket
Java对基于TCP协议的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信
函数式接口作为方法的返回值
静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
注意:自己在定义函数式接口时,@FunctionalInterface是可选的,不写这个注解,只要保证满足函数式接口的定义条件,一样时函数式接口,建议加上该注解。
数据来自于文本文件,接收到的数据写入文本文件
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket('192.168.31.77',10086);
//封装文本文件的数据
BufferedReader br = new BufferedReader(new FileReader('untitled1osw.txt'));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
//接收服务器反馈
InputStream is = s.getInputStream();
byte[] bys = new byte[1024];
int len = is.read(bys);
String data = new String(bys,0,len);
System.out.println('客户端:'+data);
}
s.close();
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
// InputStream is = s.getInputStream();
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter('untitled1copy.txt'));
String line;
while((line = br.readLine())!=null){
System.out.println('服务器:'+line);
bw.write(line);
bw.newLine();
bw.flush();
//给出反馈
OutputStream os = s.getOutputStream();
os.write('收到'.getBytes());
}
ss.close();
bw.close();
}
}
Consumer接口
有一个接口
关闭发送端
public class Demo {
public static void main(String[] args) throws IOException {
DatagramSocket ds = new DatagramSocket();
byte[] bys = 'helloworld'.getBytes();
// int length = bys.length;
// InetAddress m = Inet4Address.getByName('m');
// int port = 10086;
// DatagramPacket dp = new DatagramPacket(bys,length,m,port);
DatagramPacket dp = new DatagramPacket(bys,bys.length,Inet4Address.getByName('m'),10086);
//发送数据报包
ds.send(dp);
ds.close();
}
}
voidaccept(Tt):对给定的参数执行此操作
多线程实现文件上传练习
public class ServerThread implements Runnable {
private Socket s;
public ServerThread(Socket s) {
this.s=s;
}
@Override
public void run() {
try {
//BufferedWriter bw = new BufferedWriter(new FileWriter('untitled1copy.txt'));
//解决名称冲突问题
int count = 0;
File file = new File('untitled1copy['+count+']txt');
while (file.exists()){
count++;
file = new File('untitled1copy['+count+']txt');
}
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
System.out.println('服务器:'+line);
}
//给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write('上传成功');
bwServer.newLine();
bwServer.flush();
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
while (true){
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//为每一个客户端开启一个线程
new Thread(new ServerThread(s)).start();
}
}
}
解决办法:自定义结束标记;使用voidshutdownOutput()禁用此套接字的输出流。(输出结束)方法
格式privatestatic返回值类型方法名(参数列表){}
筛选练习
public static void main(String[] args) {
String[] ss = {'xiaohong,12','xiaocheng,15','xiaohuang,18','xiaolv,17'};
checkString(ss, s -> s.split(',')[0].length() > 8, s -> Integer.parseInt(s.split(',')[1]) > 16);
}
private static void checkString(String[] ss, Predicate p1, Predicate p2){
// return p1.test(s)&&p2.test(s);
boolean test = false;
for (String s : ss) {
test = p1.and(p2).test(s);
if (test){
System.out.println(s);
}
}
}
接口中私有方法的注意事项:
如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
Consumer
defaultPredicate
默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
组成Lambda表达式的三要素:形式参数,箭头,代码块
intgetLength()返回要发送的数据的长度或接收到的数据的长度。
注意事项:
defaultPredicate
byte[]getData()返回数据缓冲区。
练习
public static void main(String[] args) {
String[] sa = {'xiaohong,12','xiaocheng,15','xiaohuang,18'};
printInfo(sa,(String s)->{
String name = s.split(',')[0];
System.out.print('姓名'+name);
},(String s)->{
int age = Integer.parseInt(s.split(',')[1]);
System.out.println(',年龄'+age);
});
}
//定义一个方法,用不同的方式消费同一个字符串数据两次
private static void printInfo(String[] sa, Consumer con1,Consumer con2){
for (String s : sa){
con1.andThen(con2).accept(s);
}
}
范例privatevoidshow(){}
使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
Function接口
数据来自于文本文件,接收到的数据写入文本文件+给出反馈
public class Demo {
public static void main(String[] args) throws IOException {
Socket s = new Socket('192.168.31.77',10086);
//封装文本文件的数据
BufferedReader br = new BufferedReader(new FileReader('untitled1osw.txt'));
//封装输出流对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//自定义结束标识
// bw.write('886');
// bw.newLine();
// bw.flush();
//void shutdownOutput() 禁用此套接字的输出流。(输出结束)
s.shutdownOutput();
//接收服务器反馈
BufferedReader brus = new BufferedReader(new InputStreamReader(s.getInputStream()));
String data = brus.readLine();
System.out.println('服务器的反馈:'+data);
s.close();
}
}
public class ReceiveDemo {
public static void main(String[] args) throws IOException {
//ServerSocket(int port) 创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(10086);
//Socket accept() 侦听要连接到此套接字并接受它。
Socket s = ss.accept();
//获取输入流,读数据,并把数据显示在控制台
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter('untitled1copy.txt'));
String line;
while((line = br.readLine())!=null){
if ('886'.equals(line)){
break;
}
System.out.println('服务器:'+line);
bw.write(line);
bw.newLine();
bw.flush();
}
//给出反馈
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write('上传成功');
bwServer.newLine();
bwServer.flush();
ss.close();
bw.close();
}
}
引用类的实例方法
监听客户端连接,返回一个Socket对象
Consumer
public static void main(String[] args) {
operatorString('xiaohuang',(String s )->{
System.out.println(s);
});
operatorString('xiaolv',s-> System.out.println(s));
operatorString('xiaolan',System.out::println);
operatorString('xiaohei',s->
System.out.println(new StringBuilder(s).reverse().toString()));
operatorString('xiaofen',s-> System.out.println(s),s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
//定义一个方法,用不同的方式消费同一个字符串数据两次
private static void operatorString(String name, Consumer con1,Consumer con2){
// con1.accept(name);
// con2.accept(name);
con1.andThen(con2).accept(name);
}
private static void operatorString(String name, Consumer con){
con.accept(name);
}
创建一个数据包,用于接收数据
接口中默认方法
接口中和默认方法的注意事项:
如果使用方法引用,也是同样可以根据上下文进行推导
引用类方法
方法引用是Lambda的孪生兄弟
接口中有且仅有一个抽象方法
->:由应文中画线和大于符号组成,固定写法,代表指向动作
Supplier接口
voidclose();
public static void main(String[] args) throws IOException {
// Socket(InetAddress address, int port) 创建流套接字并将其连接到指定IP地址的指定端口号。
// Socket s = new Socket(Inet4Address.getByName('m'),10086);
//Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号。
Socket s = new Socket('m',10086);
//获取输出流,写数据
//OutputStream getOutputStream() 返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write('hello'.getBytes());
s.close();
}
Function
Lambda表达式被构造器替代时,它的形参全部传递给构造器作为参数
Socket(InetAddressaddress,intport)创建流套接字并将其连接到指定IP地址的指定端口号。
格式:publicstatic返回值类型方法名{}
Java位客户端提供了Socket类,位服务器端提供了ServerSocket类
体验lambda表达式
Lambda表达式格式
Lambda表达式的使用前提
从beginIndex开始到endIndex结束,截取字符串。返回一个子串,字串的长度为endIndex-beginIndex
public interface MyString {
String mySubString(String s ,int x ,int y);
}
public class MyStringDemo {
public static void main(String[] args) {
// useMyString((s,x,y)->{
// return s.substring(x,y);
// });
useMyString((s,x,y)->s.substring(x,y));
//引用类的实例方法
useMyString(String::substring);
}
private static void useMyString(MyString my){
String s = my.mySubString('HelloWorld', 2, 5);
System.out.println(s);
}
}
发送数据的步骤
如果使用Lambda,根据“可推导就可省略”原则,无需指定参数类型,也无需指定的重载形式,它们都将自动被推导
TCP接收数据
String类中的方法:publicStringtoUpperCase()将此String所有字符转换成大写
public class PrintString {
public void printUpper(String s){
System.out.println(s.toUpperCase());
}
}
public interface Printer {
void PrintUpperCase(String s);
}
public class PrinterDEmo {
public static void main(String[] args) {
// usePrinter((String s)->{
// System.out.println(s.toUpperCase());
// });
//引用对象实例方法
PrintString p = new PrintString();
usePrinter(p::printUpper);
}
private static void usePrinter(Printer p) {
p.PrintUpperCase('HelloWorld');
}
}
文章为作者独立观点,不代表股票交易接口观点