续(网络编程入门)
TCP通信练习
案例1:客户端发给服务器
package TcpSendAndReceive;
//客户端
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class ClientDemo {
public static void main(String[] args) throws IOException {
Socket s = new Socket("172.21.106.204", 10057);
//输出流,写数据
OutputStream outputStream = s.getOutputStream();
outputStream.write("hello,world!".getBytes(StandardCharsets.UTF_8));
//接收服务器反馈
InputStream inputStream = s.getInputStream();
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
System.out.println("客户端:" + new String(bys, 0, len));
s.close();
}
}
package TcpSendAndReceive;
//服务器
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//
ServerSocket ss = new ServerSocket(10057);
Socket s = ss.accept();
//输入流,读数据
InputStream inputStream = s.getInputStream();
byte[] bys = new byte[1024];
int len = inputStream.read(bys);
System.out.println("服务器:" + new String(bys, 0, len));
//给客户端反馈
OutputStream outputStream = s.getOutputStream();
outputStream.write("数据已经收到".getBytes(StandardCharsets.UTF_8));
s.close();
ss.close();
}
}
案例2:客户端发给服务器(键盘录入)
package TcpSendAndReceive;
//客户端
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//Socket对象
Socket s = new Socket("127.0.0.1", 10058);
// 键盘录入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
if (line.equals("886")) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
}
}
package TcpSendAndReceive;
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10058);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
ss.close();
}
}
案例3:客户端发给服务器(发送键盘录入,接收写入文件)
客户端发送代码和案例2一样,只需要改动服务器接收数据并写入文本
package TcpSendAndReceive;
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10058);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\Program\\itcast\\receive.txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
ss.close();
}
}
案例4:客户端数据来自文本文件,服务器写入文本文件
package TcpSendAndReceive;
//客户端
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//Socket对象
Socket s = new Socket("127.0.0.1", 10058);
// 键盘录入
BufferedReader br = new BufferedReader(new FileReader("G:\\Program\\itcast\\receive.txt"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
s.close();
br.close();
bw.close();
}
}
package TcpSendAndReceive;
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10058);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\Program\\itcast\\itcast001\\receive(1).txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
ss.close();
s.close();
bw.close();
br.close();
}
}
案例5:在案例4基础上加入反馈
package TcpSendAndReceive;
//客户端
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//Socket对象
Socket s = new Socket("127.0.0.1", 10058);
//文件
BufferedReader br = new BufferedReader(new FileReader("G:\\Program\\java_basic_learning\\itcast\\ClientDemo.java"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//结束 写入数据
s.shutdownOutput();
//接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("服务器反馈:" + brClient.readLine());
s.close();
br.close();
bw.close();
}
}
package TcpSendAndReceive;
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10058);
Socket s = ss.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\Program\\java_basic_learning\\itcast\\itcast001\\receive(1).java"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
BufferedWriter bwServer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServer.write("文件上传成功");
bwServer.newLine();
bwServer.flush();
ss.close();
s.close();
bw.close();
br.close();
}
}
案例6:结合线程
- 客户端:数据来源文件,接收服务器反馈
- 服务器:接收到的数据写入文件,给出反馈,代码用线程封装,为每一个客户端开一个线程
(客户端代码和案例5一样)
package TcpSendAndReceive;
//服务器
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10058);
while (true){
Socket s = ss.accept();
new Thread(new SeverThread(s)).start();
}
}
}
package TcpSendAndReceive;
import java.io.*;
import java.net.Socket;
public class SeverThread implements Runnable {
private Socket s;
public SeverThread(Socket s) {
this.s = s;
}
@Override
public void run() {
try {
//实现多线程不同名
int count = 1;
File file = new File("G:\\Program\\java_basic_learning\\itcast" +
"\\itcast001\\SeverCopy\\Copy[" + count + "]");
while (file.exists()) {
count++;
file = new File("G:\\Program\\java_basic_learning\\itcast\\" +
"itcast001\\SeverCopy\\Copy[" + count + "]");
}
//创建对象
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
String line;
while ((line = br.readLine())!= null){
bw.write(line);
bw.newLine();
bw.flush();
}
//给出反馈
BufferedWriter bwServe = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
bwServe.write("文件成功上传");
bwServe.newLine();
bwServe.flush();
s.close();
bw.close();
br.close();
bwServe.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package TcpSendAndReceive;
//客户端
import java.io.*;
import java.net.Socket;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//Socket对象
Socket s = new Socket("127.0.0.1", 10058);
//文件
BufferedReader br = new BufferedReader(new FileReader("G:\\Program\\java_basic_learning\\itcast\\ClientDemo.java"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
//结束写数据
s.shutdownOutput();
//接收反馈
BufferedReader brClient = new BufferedReader(new InputStreamReader(s.getInputStream()));
System.out.println("服务器反馈:" + brClient.readLine());
s.close();
brClient.close();
br.close();
bw.close();
}
}
Lambda表达式
1. Lambda表达式标准格式
接近 函数式编程思想,,接口有且仅有一个抽象方法
匿名内部类中重写run()方法的代码分析:
- 方法形式参数为空,说明调用方法时不需要传递参数
- 方法返回值类型为void,说明方法执行没有结果返回
- 方法体中的内容,是我们具体要做的事情
Lambda表达式的代码分析:
- )︰里面没有内容,可以看成是方法形式参数为空
- ->︰用箭头指向后面要做的事情
- {}:包含一段代码,我们称之为代码块,可以看成是方法体中的内容
所以组成Lambda表达式的三要素:形式参数,箭头,代码块
Lambda表达式的格式:
- 格式:(形式参数)->{代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
- ->:由英文中画线和大于符号组成,固定写法。代表指向动作
- 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
案例练习:接口,匿名内部类,Lambda三种比较
Lambda(无参数)
package Lambda;
//接口
public interface EatApple {
public void eat();
}
package Lambda;
//实现接口的类
public class EatAppleImpl implements EatApple {
@Override
public void eat() {
System.out.println("一天一苹果,医生远离我");
}
}
package Lambda;
/*测试类*/
public class Demo {
public static void main(String[] args) {
//接口实例化方式
EatApple e = new EatAppleImpl();
eatApple(e);
//匿名内部类
eatApple(new EatApple() {
@Override
public void eat() {
System.out.println("An apple a day,keeps the doctor away");
}
});
//Lambda表达式
eatApple(() -> {
System.out.println("一天一苹果,医生远离我");
});
//一天一苹果,医生远离我
//An apple a day,keeps the doctor away
//一天一苹果,医生远离我
}
public static void eatApple(EatApple e) {
e.eat();
}
}
Lambda(有参数)
package Lambda;
//接口
public interface Fly {
public void fly(String s);
}
package Lambda;
//实现接口的类
public class FlyImpl implements Fly {
@Override
public void fly(String s) {
System.out.println(s);
}
}
package Lambda;
/*测试类*/
public class Demo {
public static void main(String[] args) {
//匿名内部类
flyflyfly(new Fly() {
@Override
public void fly(String s) {
System.out.println(s);
System.out.println("飞机自驾游");
}
});
System.out.println("----------------");
//Lambda表达式
flyflyfly((String s) -> {
System.out.println(s);
System.out.println("飞机自驾游");
});
}
//晴空万里,风和日丽
//飞机自驾游
//----------------
//晴空万里,风和日丽
//飞机自驾游
public static void flyflyfly(Fly f) {
f.fly("晴空万里,风和日丽");
}
}
Lambda带参有返回值
package Lambda;
//接口
public interface Addable {
int sum(int x, int y);
}
package Lambda;
/*测试类*/
public class Demo {
public static void main(String[] args) {
getSum((int x, int y) -> {
return x + y;//30
});
getSum((int x, int y) -> {
return x * y;//200
});
}
public static void getSum(Addable s) {
int num = s.sum(10, 20);
System.out.println(num);
}
}
2. Lambda表达式的省略模式
省略规则:
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
getSum((x, y) -> x + y);//30
3. 注意事项
- 使用Lambda必须要有接口,并且要求接口中有且仅有一个抽象方法
- 必须有上下文环境,才能推导出Lambda对应的接口
根据局部变量的赋值得知Lambda对应的接口:
Runnabler r = () -> System.out.printIn("Lambda表达式");
根据调用方法的参数得知Lambda对应的接口:
new Thread(()-> System.out.printIn("Lambda表达式")).start);
4. Lambda表达式和匿名内部类的区别
所需类型不同:
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
使用限制不同:
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同:
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成