您的位置:首页 > 理论基础 > 计算机网络

用Java Serialization实现任意文件网络传输

2014-08-02 15:52 309 查看
摘要:

本文通过Java中提供的Serialization机制,通过网络(Socket)实现任意文件在不同机器之间的传输。本文将包含两个实验的代码:

1. 将文件从一个电脑(客户端),传送到另外一个电脑(服务端);

2. 将文件从一个Android
2.1手机(客户端),通过WiFi传送到电脑(服务端)。

很多朋友发现在两台机器之间,通过TCP socket传送文件的时候,所得到的文件要么比源文件大,要么比源文件小。尤其是在传递多媒体文件的时候,由于文件大小的变化,最终导致多媒体文件无法正常播放。造成这种情况的原因有很多,但100%是程序自身的问题。同样,解决的办法也有很多,本文所介绍的两个小实验,就是试图采用Java中提供的Serialization机制,来解决这样的问题。

实验一:

1. 先创建一个Java项目,项目名为ObjectClient,作为客户端应用。在这个项目中创建一个实现了Serializable接口的类FilePojo,代码如下:

package com.pnf.transfer;

import java.io.Serializable;

// 必须实现Serializable接口。否则无法调用ObjectOutputStream的

// writeObject方法,或者ObjectInputStream中的readObject方法

public class FilePojo implements Serializable

{

private static final long serialVersionUID =
1L;

private String fileName; // 文件名称

private long fileLength; // 文件长度

private byte[] fileContent; // 文件内容

public String
getFileName()

{

return fileName;

}

public void setFileName(String
fileName)

{

this.fileName =
fileName;

}

public long getFileLength()

{

return fileLength;

}

public void setFileLength(long fileLength)

{

this.fileLength =
fileLength;

}

public byte[]
getFileContent()

{

return fileContent;

}

public void setFileContent(byte[]
fileContent)

{

this.fileContent =
fileContent;

}

}

这个类将在服务器端也会被用到。

2. 编写客户端代码如下

package com.pnf.transfer;

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;

import java.net.Socket;

public class ObjectClient

{

public static void main(String[]
args)

{

String serverName = "192.168.0.10"; // 服务器IP

int port
= 6666; // 服务器端口

String filePath = "E:\\"; // 要传递文件的路径

String fileName = "full.jpg";
// 要传递文件的名称

try

{

// 连接服务器

System.out.println("Connecting
to " + serverName + " on port " +
port);

Socket client = new Socket(serverName,
port);

System.out.println("Just
connected to " + client.getRemoteSocketAddress());

// 创建FilePojo对象

FilePojo fpo = new FilePojo();

// 设定文件名

fpo.setFileName(fileName);

// 设定文件大小

File f = new File(filePath
+ fileName);

long fileLength
= f.length();

fpo.setFileLength(fileLength);

// 读取文件内容,并将其转换为byte[]

FileInputStream fis = new FileInputStream(filePath
+ fileName);

byte[]
fileContent = new byte[(int)
fileLength];

fis.read(fileContent, 0, (int)
fileLength);

fpo.setFileContent(fileContent);

// 将FilePojo对象fpo写到Socket
client指定的输出流

long start
= System.currentTimeMillis();

ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());

oos.writeObject(fpo);

long end
= System.currentTimeMillis();

System.out.println("It
takes " + (end - start) + "ms");

oos.flush();

oos.close();

}

catch(IOException
e)

{

e.printStackTrace();

}

}

}

3. 创建另外一个Java项目,项目名为ObjectServer,作为服务端应用。把第1步中的FilePojo.java拷贝到这个项目中来。

4. 编写服务端代码如下:

package com.pnf.transfer;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.net.ServerSocket;

import java.net.Socket;

public class ObjectServer

{

public static void main(String[]
args) throws ClassNotFoundException

{

ServerSocket serverSocket;

FileOutputStream fos;

try

{

serverSocket = new ServerSocket(6666);

while(true)

{

Socket clientSocket = serverSocket.accept();

// 从clientSocket获取ObjectInputStream对象

ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());

// 读取从客户端传递过来的FilePojo对象

FilePojo fpo = (FilePojo) ois.readObject();

System.out.println(fpo.getFileName());

System.out.println(fpo.getFileLength());

// 初始化FileOutputStream对象fos

fos = new FileOutputStream("D:\\" +
fpo.getFileName());

// 将fpo中的内容写入fpo

fos.write(fpo.getFileContent(), 0, (int)fpo.getFileLength());

fos.close();

ois.close();

}

}

catch(IOException
ioe)

{

ioe.printStackTrace();

}

}

}

5. 测试。

先运行服务端,在运行客户端。

在局域网上,传输的速度大致为:传输162149bytes需要20ms,即8KB/ms或8MB/s

实验二:

服务端的代码和实验一中的一样。

1. 创建一个Android项目,项目名为AndroidObjectClient作为客户端。并将实验一中的FilePojo.java拷贝到该项目中。

2. 修改main.xml如下:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<Button android:id="@+id/btn_send"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Send a picture to PC!"

>

</Button>

</LinearLayout>

3. 编写Activity的代码如下:

package com.pnf.transfer;

import java.io.File;

import java.io.FileInputStream;

import java.io.ObjectOutputStream;

import java.net.Socket;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.Toast;

public class AndroidObjectClientActivity extends Activity

implements

OnClickListener

{

private Button btn_send;

private String filePath = "/sdcard/image/";

private String fileName = "bln.jpg";

@Override

public void onCreate(Bundle
savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

btn_send =
(Button)this.findViewById(R.id.btn_send);

btn_send.setOnClickListener(this);

}

public void onClick(View
v)

{

try

{

// 建立和服务器的连接

Socket socket = new Socket("192.168.0.10",
6666);

// 创建FilePojo对象

FilePojo fpo = new FilePojo();

// 设定文件名

fpo.setFileName(fileName);

// 设定文件大小

File f = new File(filePath + fileName);

long fileLength
= f.length();

fpo.setFileLength(fileLength);

// 读取文件内容,并将其转换为byte[]

FileInputStream fis = new FileInputStream(filePath + fileName);

byte[]
fileContent = new byte[(int)
fileLength];

fis.read(fileContent, 0, (int)
fileLength);

fpo.setFileContent(fileContent);

// 将FilePojo对象fpo写到Socket
client指定的输出流

long start
= System.currentTimeMillis();

ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());

oos.writeObject(fpo);

long end
= System.currentTimeMillis();

Toast.makeText(this.getApplicationContext(), "It
takes " + (end - start) + "ms",
Toast.LENGTH_LONG).show();

oos.flush();

oos.close();

}

catch(Exception
ioe)

{

ioe.printStackTrace();

}

}

}

4. 在AndroidManifest.xml中增加permission如下(粗体字部分):

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.pnf.transfer"

android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".AndroidObjectClientActivity"

android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

<uses-sdk android:minSdkVersion="7" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.INTERNET" />

</manifest>

第一个permission,表示该程序可以读取sd卡上的内容,第二个permission,表示该程序可以联网(因为我们用到了TCP/IP)。

5. 在手机上安装编译好的AndroidObjectClient.apk。

6. 运行。

先运行服务端,再在手机上运行客户端。

在WLAN(802.11g)网上,传输的速度大致为:传输218089bytes需要200ms,即1.1KB/ms或1.1MB/s。如果是802.11n的话,传输速度应该会快很多。

当然,也可以将一个文件,通过DDMS放到模拟器中模拟的SD卡里面,然后在模拟器中运行客户端,这点在实验中也经过验证了的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java android wifi 局域网