1、对象的序列化和反序列化
- 序列化 : 能够让Java对象,通过流在网络世界里面进行传输 (对象 - > 流)
- 反序列化:让流中的序列化对象重新再变成对象 (流 - > 对象)
- 对象的序列化需要实现 Serializable (序列化的接口)
- 序列化后的对象可以在网络编程中传输
- 使用 ObjectOutputStream 来对序列化的对象进行输出
- 使用 ObjectInputStream 来对在流中传输的序列化对象来进行反序列化
参考代码,服务端
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
//我们现在需要将一个对象发送给客户端;
public class DemoListServer {
public static void main(String[] args) throws Exception {
Goods goods1 = new Goods(1, "appler");
Goods goods2 = new Goods(2, "pen");
//需要将goods对象,发送给客户端;
List<Goods> list = new ArrayList<Goods>();
list.add(goods1);
list.add(goods2);
//当有客户端连接我的服务端的时候,
//我发送我的商品信息给对方;
//1:构建一个ServerSocket对象;等待客户端连接
ServerSocket ss = new ServerSocket(8888);
System.out.println("start ... watting...");
//2: 来了连接以后,需要发送一个对象给对方;
Socket server = ss.accept();
//3:发送对象;使用输出流发送对象;
OutputStream os = server.getOutputStream();
//4:发送对象使用ObjectOutputStream
ObjectOutputStream oos = new ObjectOutputStream(os);
//一定要注意: 发送的对象,一定是可序列化的对象; 能够通过流在网络世界穿梭的对象;
oos.writeObject(list);
oos.flush(); //谁输出的,flush谁
System.out.println("send object success....");
// os.flush();//没用的
server.close();
}
}
参考代码,客户端
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.util.List;
public class DemoListClient {
static String ip = "127.0.0.1";
static int port = 8888;
public static void main(String[] args) throws Exception {
//1:首先要根据ip和端口建立一个socket
Socket client = new Socket(ip,port);
System.out.println("connection server...");
//2:接受服务端发送给我的对象;
InputStream is = client.getInputStream();
//is能够接受一个对象吗?使用对象字节流来读取一个对象;
ObjectInputStream ois = new ObjectInputStream(is);
//读取了一个对象
Object goods1 = ois.readObject();
List<Goods> list = (List)goods1;
System.out.println(goods1);
client.close();
}
}
2、Scanner(高级输入流)
作用
- 读取文件内容
- 实现控制台输入
- 从 服务器 或 客户端 接收内容
Scanner scan1 = new Scanner(System.in); //用作键盘录入
Scanner scan2 = new Scanner(new File("x.txt"));//用作文件读取
Scanner scan3 = new Scanner(socket.getInputStream());//网络通信里面去读取对方发给我的信息
scan1.nextLine();//读取键盘录入的信息
scan2.nextLine();//读取文件里面的信息
scan3.nextLine();//读取socket流里面的信息(服务端或者客户端发送的)
3、PrintWriter(高级输出流)
作用
- 给文写入件内容
- 在控制台输出
- 发送给 服务器 或者 客户端
PrintWriter pw1 = new PrintWriter(System.out);
PrintWriter pw2 = new PrintWriter("a.txt");
PrintWriter pw3 = new PrintWriter(socket.getOutputStream());
pw1.println("控制台打印");pw1.flush();
pw2.println("写到文件里面");pw2.flush();
pw3.println("发送给服务器或者客户端");pw3.flush();
4、Socket之登录注册
服务端
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class TestServer {
public static void main(String[] args) {
try {
//构建一个服务端,等待接入
ServerSocket ss = new ServerSocket(9999);
System.out.println("server is waitting...");
//获得和客户端的套接字
Socket server = ss.accept();
Scanner scan;
PrintWriter pw;
while (true){
scan = new Scanner(server.getInputStream());
pw = new PrintWriter(server.getOutputStream());
pw.println("请输入进行的操作 1:登录 2:注册 3:其他");pw.flush();
String choose = scan.nextLine();
switch (choose){
case "1":
login(scan,pw);
break;
case "2":
register(scan,pw);
break;
default:
pw.println("系统正在升级中...");pw.flush();
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
private static void login(Scanner scan, PrintWriter pw) {
pw.println("请输入用户名");pw.flush();
String user = scan.nextLine();
pw.println("请输入密码");pw.flush();
String pass = scan.nextLine();
pw.println("登录成功");pw.flush();
}
private static void register(Scanner scan, PrintWriter pw) {
pw.println("请输入注册的用户名");pw.flush();
String user = scan.nextLine();
pw.println("请输入注册的密码");pw.flush();
String pass = scan.nextLine();
pw.println("注册成功");pw.flush();
}
}
客户端单线程版
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TestClient {
public static void main(String[] args) {
String ip = "127.0.0.1";
int port = 9999;
try {
Socket client = new Socket(ip, port);
Scanner scan;
PrintWriter pw;
BufferedReader br;
while (true){
scan = new Scanner(client.getInputStream());
pw = new PrintWriter(client.getOutputStream());
//读取来自服务端的消息
String message = scan.nextLine();
System.out.println(message);
//从键盘输入操作数
br = new BufferedReader(new InputStreamReader(System.in));
message= br.readLine();
//将信息发给服务端
pw.println(message);pw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端多线程版
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class TestClientThread {
public static Socket client;
public static void main(String[] args) {
String ip = "127.0.0.1";
int port = 9999;
try {
client = new Socket(ip, port);
new ClientReaderThread().start();
new ClientWriterThread().start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接受服务端的消息
class ClientReaderThread extends Thread {
@Override
public void run() {
while(true){try {
//获取与服务端的输入流
Scanner scan = new Scanner(TestClientThread.client.getInputStream());
String message = scan.nextLine();
System.out.println(message);
} catch (IOException e) {
e.printStackTrace();
}}
}
}
//给客户端发送信息
class ClientWriterThread extends Thread {
@Override
public void run() {
while(true){
try {
Scanner scan = new Scanner(System.in);
String clientMessage = scan.nextLine();
PrintWriter pw = new PrintWriter(TestClientThread.client.getOutputStream());
pw.println(clientMessage);
pw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}