项目须要是通过WIFI建立手机和PC的通信,然后自己定义一个简单的协议对要传输的文件进行校验,传输的文件是2张3M的图片,要求考虑网络中断情况处理。

      我这里採用的是非堵塞socket来实现的,之前查过非常多资料,认为这样的比較方便,其有用传统的那种socket也是能够实现的,至于堵塞问题,能够开两个线程。这样保证读取不是同一个线程,也就能够解决。

      程序大致是这种流程,手机端发送一个“filename”字符串给PC,PC校验字符串后返回文件名称。然后手机端再把接收到的文件名称发送给PC端。进行校验,假设PC端校验成功,那么PC端就開始传输这个文件给手机端。手机端就接收这个文件。至于网络中断的问题,后来发现,仅仅要在服务端发送文件的那一段程序加入try-catch,捕获这个异常,这样服务端的程序就不会死掉,进入等待。等到手机再次和PC端建立连接。那么就能够又一次发送文件。这里是重传,而不是续传,后来想过。也仅仅有6M,实际測试过。大概2-3秒就能够传完。重传和续传意义不大,所以就简单的重传了。

      程序例如以下:

PC端:

public class MyServer {

private final static Logger logger = Logger.getLogger(MyServer.class.getName());

public static void main(String[] args) {

Selector selector = null;

ServerSocketChannel serverSocketChannel = null;

try {

selector = Selector.open();

serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.configureBlocking(false);

serverSocketChannel.socket().setReuseAddress(true);

serverSocketChannel.socket().bind(new InetSocketAddress(1991));

serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

while (selector.select() > 0) {

Iterator it = selector.selectedKeys().iterator();

while (it.hasNext()) {

SelectionKey readyKey = it.next();

it.remove();

SocketChannel socketChannel = null;

String string = "";

try {

socketChannel = ((ServerSocketChannel) readyKey.channel()).accept();

string = receiveData(socketChannel);

logger.log(Level.INFO, string);

if(string.equals("filename")){

File f= new File("D:/chz.jpg");

if (f.exists() && f.isFile()){

sendData(socketChannel, "chz.jpg");

}else{

logger.info("file doesn't exist or is not a file");

}

}

if(string.equals("chz.jpg")){

sendFile(socketChannel, new File("D:/chz.jpg"));

}

}catch(Exception ex){

logger.log(Level.SEVERE, "1", ex);

} finally {

try {

socketChannel.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "2", ex);

}

}

}

}

} catch (ClosedChannelException ex) {

logger.log(Level.SEVERE, "3", ex);

} catch (IOException ex) {

logger.log(Level.SEVERE, "4", ex);

} finally {

try {

selector.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "5", ex);

}

try {

serverSocketChannel.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "6", ex);

}

}

}

private static String receiveData(SocketChannel socketChannel) throws IOException {

String string = null;

ByteArrayOutputStream baos = new ByteArrayOutputStream();

ByteBuffer buffer = ByteBuffer.allocate(1024);

try {

byte[] bytes;

int size = 0;

while ((size = socketChannel.read(buffer)) >= 0) {

buffer.flip();

bytes = new byte[size];

buffer.get(bytes);

baos.write(bytes);

buffer.clear();

}

bytes = baos.toByteArray();

string = new String(bytes);

}catch(Exception ex){

logger.log(Level.SEVERE, "7", ex);

}finally {

try {

baos.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "8", ex);

}

}

return string;

}

private static void sendData(SocketChannel socketChannel, String string) throws IOException {

byte[] bytes = string.getBytes();

ByteBuffer buffer = ByteBuffer.wrap(bytes);

socketChannel.write(buffer);

socketChannel.socket().shutdownOutput();

}

private static void receiveFile(SocketChannel socketChannel, File file) throws IOException {

FileOutputStream fos = null;

FileChannel channel = null;

try {

fos = new FileOutputStream(file);

channel = fos.getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

int size = 0;

while ((size = socketChannel.read(buffer)) != -1) {

buffer.flip();

if (size > 0) {

buffer.limit(size);

channel.write(buffer);

buffer.clear();

}

}

}catch(Exception ex){

logger.log(Level.SEVERE, "9", ex);

} finally {

try {

channel.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "10", ex);

}

try {

fos.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "11", ex);

}

}

}

private static void sendFile(SocketChannel socketChannel, File file) throws IOException {

FileInputStream fis = null;

FileChannel channel = null;

try {

fis = new FileInputStream(file);

channel = fis.getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

int size = 0;

while ((size = channel.read(buffer)) != -1) {

buffer.rewind();

buffer.limit(size);

socketChannel.write(buffer);

buffer.clear();

}

socketChannel.socket().shutdownOutput();

}catch(Exception ex){

logger.log(Level.SEVERE, "12", ex);

} finally {

try {

channel.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "13", ex);

}

try {

fis.close();

} catch(Exception ex) {

logger.log(Level.SEVERE, "14", ex);

}

}

}

}

ANDROID端:

public class MainActivity extends Activity {

private Button mButton;

private EditText et;

private static String string;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

et = (EditText)findViewById(R.id.edittext1);

et.setText("192.168.1.214");

mButton = (Button)findViewById(R.id.button1);

mButton.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View arg0) {

// TODO Auto-generated method stub

string = et.getText().toString();

new Thread(new Runnable() {

@Override

public void run() {

// TODO Auto-generated method stub

SocketChannel socketChannel = null;

try {

socketChannel = SocketChannel.open();

SocketAddress socketAddress = new InetSocketAddress(string, 1991);

socketChannel.connect(socketAddress);

sendData(socketChannel, "filename");

String string = "";

string = receiveData(socketChannel);

if(!string.isEmpty()){

socketChannel = SocketChannel.open();

socketChannel.connect(new InetSocketAddress("192.168.1.214", 1991));

sendData(socketChannel, string);

receiveFile(socketChannel, new File("sdcard/afile/"+string));

}

} catch (Exception ex) {

Log.i("chz", null, ex);

} finally {

try {

socketChannel.close();

} catch(Exception ex) {}

}

}

}).start();

}

});

}

private void sendData(SocketChannel socketChannel, String string) throws IOException {

byte[] bytes = string.getBytes();

ByteBuffer buffer = ByteBuffer.wrap(bytes);

socketChannel.write(buffer);

socketChannel.socket().shutdownOutput();

}

private String receiveData(SocketChannel socketChannel) throws IOException {

String string = null;

ByteArrayOutputStream baos = new ByteArrayOutputStream();

try {

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

byte[] bytes;

int count = 0;

while ((count = socketChannel.read(buffer)) >= 0) {

buffer.flip();

bytes = new byte[count];

buffer.get(bytes);

baos.write(bytes);

buffer.clear();

}

bytes = baos.toByteArray();

string = new String(bytes);

// socketChannel.socket().shutdownInput();

} finally {

try {

baos.close();

} catch(Exception ex) {}

}

return string;

}

private static void sendFile(SocketChannel socketChannel, File file) throws IOException {

FileInputStream fis = null;

FileChannel channel = null;

try {

fis = new FileInputStream(file);

channel = fis.getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

int size = 0;

while ((size = channel.read(buffer)) != -1) {

buffer.rewind();

buffer.limit(size);

socketChannel.write(buffer);

buffer.clear();

}

socketChannel.socket().shutdownOutput();

} finally {

try {

channel.close();

} catch(Exception ex) {}

try {

fis.close();

} catch(Exception ex) {}

}

}

private static void receiveFile(SocketChannel socketChannel, File file) throws IOException {

FileOutputStream fos = null;

FileChannel channel = null;

try {

fos = new FileOutputStream(file);

channel = fos.getChannel();

ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

int size = 0;

while ((size = socketChannel.read(buffer)) != -1) {

buffer.flip();

if (size > 0) {

buffer.limit(size);

channel.write(buffer);

buffer.clear();

}

}

} finally {

try {

channel.close();

} catch(Exception ex) {}

try {

fos.close();

} catch(Exception ex) {}

}

}

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.main, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

if (id == R.id.action_settings) {

return true;

}

return super.onOptionsItemSelected(item);

}

}

      番外:事实上做这个文件传输遇到的最头痛的问题不是程序难不难写。而是wifi通信的建立。最初我是用自己win7的电脑连路由器。然后手机也连路由器做的測试,没有问题。但是后来项目需求是下位机是一台XP的电脑。并且要求点对点建立wifi,所以仅仅能有一端设成wifi热点。还有一端连接这个热点。设想非常完美,然后找了实验室唯一一台XP电脑測试了两天,都没有可以让我手机连上PC。后来各种问,才知道XP不支持为android创wifi热点,真心坑呀。然后我就想反过来做呗,手机建wifi热点,电脑连。耶果然连上了,但是。明明写好的程序,各种执行不了,最后手机巨热,(我心痛死我的小米。求不黑小米。真心一直用小米,仅仅是导师不给配开发手机,仅仅能用自己手机,哎)所以直接pass这个想法,最后百度了一下。貌似可以接外接硬件设备,例如说360随身wifi硬件,嗯导师最终答应淘宝买一个来測试下,今天买吧。

       哦,整个程序參考了两位大神博客:http://www.cnblogs.com/hongten/archive/2012/04/29/java_socket.html

 http://blog.csdn.net/kongxx/article/details/7288896尤其是后面这位大神的一个专栏专门讲java socket的。讲得非常好。

      这个文件传输的整个project地址:http://download.csdn.net/detail/u012321815/8047863



查看原文