`

JAVA Socket传输数据和对象

    博客分类:
  • JAVA
阅读更多
1   引子

               在Socket通信中,我们要在客户端和服务端中传输数据,传输的数据有各种类型,int,short,long以及String,甚至是自定义的各种Object,我们如何能够保证在服务端和客户端之间的数据能够使得两端都能理解,这就是所谓的“应用协议”;

在通信的“管道”中,流的都是二进制数据,所以,双方如何约定好“解析规则”,则就必须要求通信双方都预先制定好协议;

2   序列化和反序列化

在Java中,有一个借口Serializable接口,这个接口不需要实现实现任何方法,只是一个标识,Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来。重新构造一个相同的对象。这种机制允许你将对象通过网络进行传播,并可以随时把对象持久化到数据库、文件等系统里。

代码如下:

Person:

import java.io.Serializable;

import java.util.Date;

 

public class Person implements Serializable {

         private String name;

         private int tall;

         private transient Date birthday;

         private Address address;

 

         public String getName() {

                   return name;

         }

 

         public void setName(String name) {

                   this.name = name;

         }

 

         public int getTall() {

                   return tall;

         }

 

         public void setTall(int tall) {

                   this.tall = tall;

         }

 

         public Date getBirthday() {

                   return birthday;

         }

 

         public void setBirthday(Date birthday) {

                   this.birthday = birthday;

         }

 

         public Address getAddress() {

                   return address;

         }

 

         public void setAddress(Address address) {

                   this.address = address;

         }

 

}

 

Address:

package stream.demo;

 

import java.io.Serializable;

 

public class Address implements Serializable{

         private String city;

         private String street;

 

         public Address() {

         }

 

         public Address(String city, String street) {

                   this.city = city;

                   this.street = street;

         }

 

         public String getCity() {

                   return city;

         }

 

         public void setCity(String city) {

                   this.city = city;

         }

 

         public String getStreet() {

                   return street;

         }

 

         public void setStreet(String street) {

                   this.street = street;

         }

 

}

我们将这个对象串行化至文件系统,然后将之还原,这个过程其实类似于一个“压扁”和“充气”的过程,请注意,我们的Person类中包含一个嵌入对象,并且birthday变化,将之设置为transient限定符,这表示我们放弃了birthday的串行化;
package stream.demo;

 

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.OutputStream;

import java.util.Date;

 

public class Persistence {

         public static void main(String[] args) {

                   Persistence.savePerson();

                   Persistence.getPerson();

         }

 

         public static void getPerson() {

                   try {

                            InputStream in = new FileInputStream("c:\\person.dat");

                            ObjectInputStream dataInput = new ObjectInputStream(in);

                            Person p = (Person) dataInput.readObject();

                            System.out.println(p.getName());

                            System.out.println(p.getTall());

                            System.out.println(p.getBirthday());

                            System.out.println(p.getAddress().getCity());

                            System.out.println(p.getAddress().getStreet());

                   } catch (Exception e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

         }

 

         public static void savePerson() {

                   Person p = new Person();

                   p.setName("corey");

                   p.setTall(171);

                   p.setBirthday(new Date());

                   p.setAddress(new Address("yiyang", "ziyang"));

                   OutputStream out = new ByteArrayOutputStream();

                   try {

                            OutputStream fileOut = new FileOutputStream(new File(

                                               "c:\\person.dat"));

 

                            ObjectOutputStream dataOut = new ObjectOutputStream(fileOut);

                            dataOut.writeObject(p);

 

                            dataOut.close();

                            fileOut.close();

                   } catch (IOException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

         }

}


可见,我们的目的实现了,并且birthday没有被串行化;如果我们不讲Address实现Serializable,会发生异常:

java.io.WriteAbortedException: writing aborted



3   IO流

我们都知道JAVA的IO是一个极其庞大的类家族,也正是运用了装饰模式的经典场景;



可见,我们一部分管道是直接连接了数据源,或者直接输出到数据源,他们能够直接读数据或者写数据,我们上一节中使用的FileoutputStream和FileInputStream就是这样的管道,他们的数据源就是指存在文件系统中的文件;下一部分我们要求使用的ByteArrayInputStream和ByteArrayOutputStream也是这样的管道,不过他的数据源是存在内存中的数组;他能够通过write把数据,字符串等等写进这块数组区域,并且能够得到一个完整的字节数组;

而另外的一部分则不能直接与数据源发生读写交互,他主要用于装饰上一部分的管道,给这个管道赋予更加便捷的功能,诸如BufferedReader等等的,主要是提供了缓存,就好比给上一部分管道中间提供了一个“蓄水池”,这个“蓄水池”等到“水流”到了一定的程度的时候,才会一次性的流进或者流出等等,诸如ObjectInputStream和ObjectOutputStream,他们能够直接读写一个Object,但是这个Object被写到了哪里,是内存中的字节数组还是文件文件的文件中,而必须委托给其他管道实现;



4   在网络中传输对象

在网络中的两台机器中传输对象,前提首先是基于同一个平台,这是序列化的基础,所以这里主要有两种做法:



l  采用JAVA的序列化机制,将对象“压扁”成二进制字节,将二进制字节在网络中传输;

l  自定义协议,将对象用字符串描述出来,将字符串用二进制表示,在网络中传输,在另外一边用相反的策略解析这个字符串,重新构造业务对象,这个方法能够在异构平台中进行传输而不变形,但是需要额外的编写“压扁”和“充气”的代码;



我们这里用第一种方法:
可见,我们的目的实现了,并且birthday没有被串行化;如果我们不讲Address实现Serializable,会发生异常:

java.io.WriteAbortedException: writing aborted

 

3   IO流

我们都知道JAVA的IO是一个极其庞大的类家族,也正是运用了装饰模式的经典场景;

 

可见,我们一部分管道是直接连接了数据源,或者直接输出到数据源,他们能够直接读数据或者写数据,我们上一节中使用的FileoutputStream和FileInputStream就是这样的管道,他们的数据源就是指存在文件系统中的文件;下一部分我们要求使用的ByteArrayInputStream和ByteArrayOutputStream也是这样的管道,不过他的数据源是存在内存中的数组;他能够通过write把数据,字符串等等写进这块数组区域,并且能够得到一个完整的字节数组;

而另外的一部分则不能直接与数据源发生读写交互,他主要用于装饰上一部分的管道,给这个管道赋予更加便捷的功能,诸如BufferedReader等等的,主要是提供了缓存,就好比给上一部分管道中间提供了一个“蓄水池”,这个“蓄水池”等到“水流”到了一定的程度的时候,才会一次性的流进或者流出等等,诸如ObjectInputStream和ObjectOutputStream,他们能够直接读写一个Object,但是这个Object被写到了哪里,是内存中的字节数组还是文件文件的文件中,而必须委托给其他管道实现;

 

4   在网络中传输对象

在网络中的两台机器中传输对象,前提首先是基于同一个平台,这是序列化的基础,所以这里主要有两种做法:

 

l  采用JAVA的序列化机制,将对象“压扁”成二进制字节,将二进制字节在网络中传输;

l  自定义协议,将对象用字符串描述出来,将字符串用二进制表示,在网络中传输,在另外一边用相反的策略解析这个字符串,重新构造业务对象,这个方法能够在异构平台中进行传输而不变形,但是需要额外的编写“压扁”和“充气”的代码;

 

我们这里用第一种方法:
package stream.demo;

 

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.OutputStream;

import java.util.Date;

 

public class Persistence {

         public static void main(String[] args) {

                   byte[] bs = Persistence.toBytes();

        //在网络中进行传输

                   Persistence.getBytes(bs);

         }

 

         public static byte[] toBytes() {

                   Person p = new Person();

                   p.setName("corey");

                   p.setTall(171);

                   p.setBirthday(new Date());

                   p.setAddress(new Address("yiyang", "ziyang"));

                   ByteArrayOutputStream out = new ByteArrayOutputStream();

                   try {

                            ObjectOutputStream oout = new ObjectOutputStream(out);

                            oout.writeObject(p);

                   } catch (IOException e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

                   return out.toByteArray(); 

         }

 

         public static void getBytes(byte[] bs) {

                   try {

                            ByteArrayInputStream byteIn = new ByteArrayInputStream(bs);

                            ObjectInputStream in = new ObjectInputStream(byteIn);

                            Person p = (Person) in.readObject();

                            System.out.println(p.getName());

                            System.out.println(p.getTall());

                            System.out.println(p.getBirthday());

                            System.out.println(p.getAddress().getCity());

                            System.out.print(p.getAddress().getStreet());

                   } catch (Exception e) {

                            // TODO Auto-generated catch block

                            e.printStackTrace();

                   }

         }

}

 

其中服务端代码片段为:

in = this.getRequestSocket().getInputStream();

                            out = this.getRequestSocket().getOutputStream();

                            byte[] bs = Persistence.toBytes();

                            System.out.println("发送数字长度:"+bs.length);

                            out.write(bs);

                            this.getRequestSocket().close();

 

客户端代码片段为:

InputStream in = request.getInputStream();

                            byte[] bin = new byte[200];

                            int length = 0;

                            while ((length = in.read(bin)) != -1) {

                                     System.out.println("length:" + length);

                                     Persistence.getBytes(bin);

                            }

其中,服务端代码和客服端代码都引用了Person 的jar包;
分享到:
评论
4 楼 xiao_bodian 2012-05-24  
我现在有ArrayList<String>,需要用这种方法传输吗?我现在不确定怎么传
3 楼 ywx217 2012-05-16  
收获很多,感谢楼主。
2 楼 eason26_li 2010-07-19  
youshini 写道
首先谢谢您的分享。在socket中测试了下,发现Date数据类型在接收的时候是null(即接收到的是null,而不是预期的结果)。请问你出现这样的情况吗?麻烦解答下,谢谢。

我这边没问题呀,你的Date是否用得java.util包中的?
1 楼 youshini 2010-06-05  
首先谢谢您的分享。在socket中测试了下,发现Date数据类型在接收的时候是null(即接收到的是null,而不是预期的结果)。请问你出现这样的情况吗?麻烦解答下,谢谢。

相关推荐

    java socket使用加密协议传输对象

    ### Java Socket 使用加密协议传输对象:深入解析与实践 在当今互联网时代,数据安全成为企业和个人用户关注的焦点。在Java开发中,Socket编程是一种常见的网络通信方式,它允许不同计算机上的应用程序通过网络进行...

    java使用Socket类接收和发送数据

    Java中的Socket类是进行网络通信的核心组件,它主要用于实现客户端与服务器之间的TCP连接,从而进行双向数据传输。本文将深入探讨如何使用Socket类接收和发送数据。 首先,我们需要理解Socket类的基本概念。Socket...

    java socket传输demo

    在这个"java socket传输demo"中,我们将深入探讨Java如何使用Socket类来实现客户端和服务器端之间的数据交换。 首先,Socket是Java提供的一个类,位于`java.net`包下,它代表了网络上的两个应用程序之间的一个双向...

    JAVA socket收发数据,并支持断网自动连接

    - 一旦连接建立,客户端和服务器都可以通过`Socket`对象的`getInputStream()`和`getOutputStream()`方法获取输入/输出流,进行数据的读写操作。 - 使用`DataInputStream`和`DataOutputStream`可以方便地进行基本...

    Java Socket 聊天通信演示代码

    首先,Java Socket通信基于TCP(传输控制协议),它确保了数据的可靠传输,包括数据的顺序和无丢失。在聊天应用中,服务器端创建一个Socket监听特定的端口,等待客户端的连接请求。一旦客户端连接到服务器,它们之间...

    通过java socket实现屏幕网络监控

    在Java中,`java.net.Socket` 和 `java.net.ServerSocket` 是两个主要的类,分别代表客户端和服务器端的Socket。客户端Socket用于连接到服务器,而服务器端Socket则监听特定端口,等待客户端的连接请求。 在屏幕...

    Java实现Socket长连接和短连接

    - 数据传输:通过Socket对象的输入/输出流进行数据的发送和接收。 - 关闭连接:完成通信后,双方都会调用Socket的close()方法关闭连接。 **2. 长连接(Long Connection)** 长连接则用于需要持续交互或多次通信的...

    java socket 图片传输

    在Java中,可以利用Socket类创建客户端和服务器端进行数据交互。其中,`ServerSocket`类用于创建服务器端套接字,而`Socket`类用于创建客户端套接字。 #### 三、图片传输原理 通过Socket进行图片传输的过程主要包括...

    Java socket文件传输实例

    在这个"Java socket文件传输实例"中,我们将深入探讨如何使用Java的Socket类进行文件的发送和接收,这对于理解网络编程的基本原理以及在实际应用中构建文件共享系统至关重要。 首先,Java Socket是基于TCP/IP协议的...

    JAVA Socket通信示例

    在这个"JAVA Socket通信示例"中,我们可能会看到如何通过Socket类来创建连接,实现数据的单工、半双工和全双工传输。下面我们将深入探讨这些通信模式以及如何在Java中实现它们。 **1. 单工通信:** 单工通信是一种...

    Java Socket网络编程.pdf

    在Java中,Socket编程主要涉及两个关键类:`ServerSocket`和`Socket`。`ServerSocket`类用于服务器端,它监听指定端口的连接请求。创建一个`ServerSocket`实例,例如`ServerSocket server = new ServerSocket(9998);...

    Java socket编程实现两台主机间的通信

    Java Socket 编程实现两台主机间的通信 Java Socket 编程是 Java 语言中用于实现网络通信的编程...通过了解 Java Socket 编程的原理、实现方法和应用场景,可以更好地应用 Java Socket 编程来实现网络通信和数据传输。

    java socket工具类示例

    Java Socket工具类是Java网络编程中的重要组成部分,它提供了客户端和服务器端进行双向通信的基础。在本示例中,我们将探讨如何使用Java Socket创建一个简单的控制台聊天系统,包括客户端(client)和服务器端...

    java socket 经典版本

    Java中的Socket主要使用流式Socket,因为它们提供面向连接、可靠的数据传输服务。 1. **创建Socket与ServerSocket**: - 客户端使用`Socket`类创建一个Socket实例,并指定服务器的IP地址和端口号,从而建立到...

    java socket 简单的文件传输程序

    Java Socket 是Java编程语言中用于实现网络通信的核心API,它基于TCP/IP协议栈,提供了低级别的数据传输控制。在这个简单的文件传输程序中,我们主要关注的是如何使用Socket进行文件的发送与接收。以下是对该程序...

    Java Socket聊天室

    在Socket编程中,通常会使用Socket对象的getInputStream()和getOutputStream()方法获取与之关联的输入输出流,然后通过这些流进行数据的读写操作。 4. **设计模式**: 为了实现聊天室的功能,可能还会涉及到一些...

    基于SOCKET的数据传输安全技术研究——以JAVA SOCKET为例.pdf

    针对Socket数据传输的安全性研究,本文总结了三种主要的技术手段:对象序列化、数字签名和SSL协议。对象序列化是指将对象状态信息转换为可以存储或传输的形式的过程,Java通过ObjectOutputStream和ObjectInputStream...

    java socket 中文教程

    本教程将深入探讨Java Socket的相关知识点,旨在帮助开发者理解和掌握如何在Java环境中构建网络应用程序。 一、Socket基础 Socket在计算机网络中扮演着桥梁的角色,连接了两个网络进程进行数据传输。Java Socket类...

    Java Socket 实现SMTP邮件发送,支持SSL/TSL

    在本案例中,我们将关注如何使用Java Socket来实现SMTP(Simple Mail Transfer Protocol)邮件发送,并支持SSL(Secure Sockets Layer)和TLS(Transport Layer Security)安全协议。 SMTP是一种互联网标准,用于在...

    利用socket连续发送与连续接收数据

    在IT领域,网络编程是不可或缺的一部分,而Socket编程则是实现网络...连续发送和接收数据的场景在许多应用中都很常见,比如文件传输、在线聊天等。通过理解和掌握Socket编程,开发者可以构建出高效且可靠的网络应用。

Global site tag (gtag.js) - Google Analytics