Warning:并没有解决问题,只是换了条路
0. 陈述流程
首先A和C是客户端,B是服务器,A发送内容B接收内容后对内容修改并转发到C,其实代码是双向的,这里简化一下,只让A发送
发送的消息是ClientMsg对象,对象内有int和String还有对象people,people对象内有int和String。
B需要修改的内容只是people,其他不做修改
ClientMsg类(没在图上的的是get和set方法)
people类
服务器的修改并转发
1. 遇到问题
A发送消息后由B接收,此时没有问题,B接收后对接收的ClientMsg对象内部的people对象修改,修改后客户端接收到的却是修改之前的内容
2.排查问题
在服务端接收到消息后和转发消息后打印消息,显示的是已经修改,并且在删除掉people对象的toString方法后打印的内存地址值也是已经修改的,但是接收端接收的却是修改前的消息,试着修改一下写法:
原来:直接修改people对象,然后把people对象放入ClientMsg对象
修改后:修改ClientMsg对象内部people对象的Id
发现修改后的写法可以了
3.问题原因
这个在我写这个博客的时候我还不太清楚,问了问认识的大手子,他说是因为序列化和反序列化的原因
4.解决办法
不用ObjectInputStream与ObjectOutputStream,改用JSON,而且JSON的序列化效率还比java快,
这条路难走就走另一条路,更何况另一条路还更好(滑稽)
下边的链接是JSON和ObjectOutputStream速度比较的一个博客
Java ObjectOutputStream序列化与JSON序列化大比拼
4.代码
Server.java
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
public class Server {
// 分配给socket连接的id,用于区分不同的socket连接
private static int id = 0;
private static int now = 0;
// 存储socket连接,发送消息的时候从这里取出对应的socket连接
private static HashMap<Integer, ServerThread> socketList = new HashMap<>();
private ServerSocket server;
private static people people;
private static people people1;
public Server(int port) {
people = new people(911, "如果看到这句话就是直接修改CilentMsg的对象");
people1 = new people(999, "如果看到这句话就是修改CilentMsg的people的name");
try {
this.server = new ServerSocket(port);
System.out.println("服务器启动完成 使用端口: " + port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
try {
while (true) {
Socket socket = server.accept();
System.out.println(++id + ":客户端接入:" + socket.getInetAddress() + ":" + socket.getPort());
ServerThread thread = new ServerThread(id, socket);
socketList.put(id, thread);
thread.run();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 服务线程,当收到一个TCP连接请求时新建一个服务线程
private class ServerThread implements Runnable {
private int id;
private Socket socket;
private InputStream in;
private OutputStream out;
private ObjectInputStream oin;
private ObjectOutputStream oot;
ServerThread(int id, Socket socket) {
try {
this.id = id;
this.socket = socket;
this.in = socket.getInputStream();
this.out = socket.getOutputStream();
this.oin = new ObjectInputStream(in);
this.oot = new ObjectOutputStream(out);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
new Reader().start();
}
public void send(ClientMsg data) {
if (!socket.isClosed() && data != null) {
try {
oot.writeObject(data);
oot.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void close() {
try {
if (oin != null)
oin.close();
if (oot != null)
oot.close();
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
socketList.remove(id);
} catch (IOException e) {
e.printStackTrace();
}
}
private class Reader extends Thread {
@Override
public void run() {
try {
ClientMsg clientMsg;
while (!socket.isClosed()) {
clientMsg = (ClientMsg) oin.readObject();
System.out.println(id + ":接受到的Msg:\n " + clientMsg);
people.setAge(now);
people1.setAge(now);
if (clientMsg.getId() == 8) {
clientMsg.setPeople(people1);
System.out.println("直接修改对象内的people");
} else {
clientMsg.getPeople().setAge(now);
System.out.println("修改信息对象内people的id");
}
System.out.println("修改后的ClientMsg对象\n" + clientMsg);
System.out.println("now" + now);
now++;
//转发
if (socketList.size() > 1)
socketList.get(id == 1 ? 2 : 1).send(clientMsg);
}
// 如果循环中断说明连接已断开
System.out.println(id + ":客户端主动断开连接");
close();
} catch (IOException | ClassNotFoundException e) {
System.out.println(id + ":连接已断开");
} finally {
close();
}
}
private int numUP(int num) {
return (num++);
}
}
}
public static void main(String[] args) {
new Server(8080).start();
}
}
Client.java
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
public class Client {
private Socket socket;
private InputStream in;
private OutputStream out;
private static ObjectInputStream oin;
private static ObjectOutputStream oot;
private Client(String address, int port) {
try {
socket = new Socket(address, port);
in = socket.getInputStream();
out = socket.getOutputStream();
oot = new ObjectOutputStream(out);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("客户端启动成功");
}
public void start() {
// 和服务器不一样,客户端只有一条连接,能省很多事
Reader reader = new Reader();
Writer writer = new Writer();
reader.start();
writer.start();
}
public void close() {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
if (socket != null) {
socket.close();
}
System.exit(0);
} catch (IOException e) {
e.printStackTrace();
}
}
private class Reader extends Thread {
public Reader() {
}
@Override
public void run() {
try {
ClientMsg clientMsg;
if (oin == null)
oin = new ObjectInputStream(in);
System.out.println("输入a,Msg的Id为8,服务端会直接修改Msg的people对象\n输入不是a,msg的Id为9,服务端会修改Msg的people对象的id");
while (!socket.isClosed()) {
clientMsg = (ClientMsg) oin.readObject();
System.out.println("Server\n" + clientMsg);
}
System.out.println("服务器主动断开连接");
close();
} catch (ClassNotFoundException | IOException e) {
System.out.println("连接已断开");
} finally {
close();
}
}
}
private class Writer extends Thread {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
@Override
public void run() {
try {
String line = "";
while (!socket.isClosed() && line != null && !"exit".equals(line)) {
line = reader.readLine();
//数据只是随便写的,主要是为了测试
if ("a".equals(line)) {
oot.writeObject(new ClientMsg(8, line, new people(0, "是A")));
} else {
oot.writeObject(new ClientMsg(9, line, new people(0, "不是A")));
}
}
System.out.println("客户端退出");
close();
} catch (IOException e) {
System.out.println("error:连接已关闭");
} finally {
close();
}
}
}
public static void main(String[] args) {
// String address = args[0];
// int port = Integer.parseInt(args[1]);
// new Client(address, port).start();
new Client("127.0.0.1", 8080).start();
}
}
people.java
import java.io.Serializable;
import java.util.ArrayList;
public class people implements Serializable {
private int age;
private String name;
public people(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// @Override
// public String toString() {
// return "people{" +
// "age=" + age +
// ", name='" + name + '\'' +
// '}';
// }
}
ClientMsg.java
import java.io.Serializable;
public class ClientMsg implements Serializable {
private int id;
private String msg;
private people people;
public ClientMsg(int id, String msg, people people) {
this.id = id;
this.msg = msg;
this.people = people;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public people getPeople() {
return people;
}
public void setPeople(people people) {
this.people = people;
}
@Override
public String toString() {
return "ClientMsg{" +
"id=" + id +
", msg='" + msg + '\'' +
", people=" + people +
'}';
}
}