Sokect传输对象


流程

可以理解为是对TCP的实现。

服务端

  1. 创建ServerSocket对象,绑定监听端口

  2. 通过accept0方法监听客户端请求

  3. 连接建立后,通过输入流读取客户端发送的请求信息

  4. 通过输出流向客户端发送响应信息

  5. 关闭相关资源

客户端 :

  1. 创建Socket对象,指明需要连接的服务器的地址和端口号

  2. 连接建立后,通过输出流向服务器端发送请求信息

  3. 通过输入流获取服务器响应的信息

  4. 关闭相关资源

序列化和反序列化

对象输出流和对象输入流(ObjectOutputStream和ObjectInputStream)只能将支持 java.io.Serializable 接口的对象写入流中。需要传递的类必须实现需要实现Serializable接口接口。

@Data
@ToString
//需要实现Serializable接口
public class AuthorityEntity implements Serializable {
    private int id;
    private String authority1 = "off";
    private String authority2 = "off";
    private String authority3 = "off";
    private String authority4 = "off";
    private String authority5 = "off";
    private String authority6 = "off";
    private String authority7 = "off";
}
  • 序列化:将一个特定的数据结构转换为一组字节的过程。ObjectOutputStream
  • 反序列化:将一组字节转换为特定的数据结构的过程。ObjectInputStream

ObjectOutputStream

将 Java 对象的基本数据类型和图形写入 OutputStream。

可以使用 ObjectInputStream 读取(重构)对象。

通过在流中使用文件可以实现对象的持久存储。

如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

常用方法:
//将指定的对象写入 ObjectOutputStream。
public final void writeObject(Object obj);
如:

OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(authorityEntity);

ObjectInputStream

对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

常用方法:
//从 ObjectInputStream 读取对象。
public final Object readObject();
如:

InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
//必须保证服务端和客户端的 对象 包名一致
log.info("客户端发送的对象:" + ois.readObject());

实现

  1. 创建服务端Socket:ServerSocket

    创建客户端Socket:Socket;

  2. 打开连接到Socket的InputStream/OutputStream;

  3. 按照协议对Socket进行读写操作;

  4. 关闭InputStream和OutputStream和Socket。

服务端

/**
 * 接受请求并开起处理线程
 */
public class ContractPart {

    public static void main(String arg[]) {
        try {
            ServerSocket serverSocket = new ServerSocket(9998);
            int count = 0;//记录客户端的数量
            System.out.println("服务器启动,等待客户端的连接。。。");
            Socket socket = null;
            while (true) {
                socket = serverSocket.accept();
                ++count;
                Thread serverHandleThread = new Thread(new ServerHandleThread(socket));
                serverHandleThread.setPriority(4);
                serverHandleThread.start();
                System.out.println("上线的客户端有" + count + "个!");
                InetAddress inetAddress = socket.getInetAddress();
                System.out.println("当前客户端的IP地址是:" + inetAddress.getHostAddress());
            }
        } catch (IOException e) {//TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

/**
 * 服务器对socket进行处理的线程
 */

class ServerHandleThread implements Runnable {
    Socket socket = null;
    public ServerHandleThread(Socket socket) {
        super();
        this.socket = socket;
    }

    @Override
    public void run() {//TODO Auto-generated method stub
        OutputStream os = null;
        PrintWriter pw = null;
        try {
            InputStream is = socket.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
            //readObject()方法必须保证服务端和客户端的 对象 包名一致,要不然会出现找不到类的错误
            System.out.println("客户端发送的对象:" + ois.readObject());
            socket.shutdownInput();//禁用套接字的输入流
            os = socket.getOutputStream();
            pw = new PrintWriter(os);
            pw.println("欢迎登录!");
            pw.flush();
            socket.shutdownOutput();
        } catch (IOException | ClassNotFoundException e) {//TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (pw != null) {
                    pw.close();
                }
                if (os != null) {
                    os.close();
                }
                if (socket != null) {
                    socket.close();
                }
            } catch (IOException e) {//TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

客户端

public static void main(String arg[]) throws IOException {
        try {
            //1.创建客户端的Socket,指定服务器的IP和端口
            Socket socket = new Socket("454585x8l0.qicp.vip", 14031);
            //2.获取该Socket的输出流,用来向服务器发送信息
            OutputStream os = socket.getOutputStream();
            //将对象序列化,转为字节
            ObjectOutputStream oos = new ObjectOutputStream(os);
            //对象写入输出流
            AuthorityEntity authorityEntity = new AuthorityEntity();
            oos.writeObject(authorityEntity);
            socket.shutdownOutput();
            String infoString = null;
            //3.获取输入流,取得服务器的信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println("服务器端的信息:" + info);
            }
            socket.shutdownInput();
            oos.close();
            os.close();
            is.close();
            br.close();
            socket.close();
        } catch (UnknownHostException e) {//TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {//TODO Auto-generated catch block
            e.printStackTrace();
        }
}

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。

传输多个参数

分别添加各个参数,可以是同类。但接受方顺序必须保持一致

//客户端
oos.writeObject(alarmRecordEntity );
oos.writeObject("1" );
oos.writeObject("2" );

//服务端
System.out.println((AlarmRecordEntity)ois.readObject());
System.out.println((String) ois.readObject());
System.out.println((String) ois.readObject());


文章作者: Luan-bx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Luan-bx !
  目录