当前位置: 移动技术网 > IT编程>开发语言>Java > java基于Socket做一个简单下载器

java基于Socket做一个简单下载器

2019年07月22日  | 移动技术网IT编程  | 我要评论

本文实例为大家分享了java基于socket制作下载器的过程,及相关代码,供大家参考,具体内容如下

1.首先要建立一个服务器用来处理信息并给客户端传输文件(电脑)
 我是用电脑开了一个wifi,手机连上后使用scoket传输的 
serverip要根据自己实际情况更改。端口也可以随便更改0~65535,尽量选大一点 

import java.io.bufferedinputstream;
import java.io.bufferedoutputstream;
import java.io.bufferedreader;
import java.io.bufferedwriter;
import java.io.file;
import java.io.fileinputstream;
import java.io.inputstreamreader;
import java.io.outputstreamwriter;
import java.io.printwriter;
import java.net.serversocket;
import java.net.socket;

/**
 * 测试android客户端与pc服务器通过socket进行交互 服务器端:接收客户端的信息并回送给客户
 * 
 * @author ameyume
 * 
 */
public class server implements runnable {
 //定义传输的ip和端口信息
 public static final string serverip = "192.168.155.1";
 //定义的9888端口
 public static final int serverport = 9888;
 //定义文件
 private file file = null;
 
 public static void main(string[] args) {
 //建立调用线程执行传输的方法
 thread desktopserverthread = new thread(new server());
 desktopserverthread.start();
 }
 
 public void run() {
 try {
  system.out.println("s: connecting...9888");

  //创建套接字
  serversocket serversocket = new serversocket(serverport);
  while (true) {
  // 等待接受客户端请求
  socket client = serversocket.accept();

  system.out.println("s: receiving...9888");

  try {

   // 接受客户端信息
   bufferedreader in = new bufferedreader(
    new inputstreamreader(client.getinputstream()));
   system.out.println("s: 接收客户端信息");
   // 读取客户端的信息
   string str = in.readline();
   string str1 = str.substring(0,2);
   string str2 = str.substring(2);
   system.out.println(str);
   //根据客户端的请求找到对应的文件并把文件大小的值传过去
   if (str.equals("file_size")) {
   
   //定义你要传输的文件(我这里写的是e盘下的某个文件)
   file = new file("e:\\某个文件");
   //输入流
   fileinputstream fis = new fileinputstream(file);
   //输出流
   bufferedinputstream bis = new bufferedinputstream(fis);
   //计算将要传输的文件大小
   int sum = bis.available();
   //将int型的文件大小转成字符串
   string s = string.valueof(sum);
   system.out.println(s);
   //建立输出流以发送文件大小的信息
   printwriter out = new printwriter(new bufferedwriter(
    new outputstreamwriter(client.getoutputstream())),
    true);
   //发送文件的大小信息
   out.println(s);
   //关闭流
   out.flush();
   bis.close();

   } else if (str1.equals("ok")) {
   int a = integer.parseint(str2);
   
   // 客户端收到文件大小的值后,再根据客户端传来的“ok”将文件传过去
   bufferedoutputstream bos = new bufferedoutputstream(
    client.getoutputstream());
   
   system.out.println("s: 开始传输");

   //开始传输
   if (true) {
    //输入流
    fileinputstream fis = new fileinputstream(file);
    //跳过前面已经传输过的字节
    fis.skip(a);
    //缓冲输入流
    bufferedinputstream bis = new bufferedinputstream(
     fis);

    int t = -1;
    while ((t = bis.read()) >= 0) {
    bos.write(t);
    }

    string s = "已传输";
    //关闭流
    bos.flush();
    bis.close();
    bos.close();
    // serversocket.close();

    system.out.println("s: received: '" + s + "'");
   }
   } else {
   system.out
    .println("not receiver anything from client!");
   }
  } catch (exception e) {
   system.out.println("s: error 1");
   e.printstacktrace();
  } finally {
   client.close();
   system.out.println("s: done.");
  }
  }
 } catch (exception e) {
  system.out.println("s: error 2");
  e.printstacktrace();
 }
 }

}

 2.再建立一个客户端,我这里用的是安卓写的mainactivity.java(我是在手机上运行的) 

package com.xhy.zz;

import android.app.activity;
import android.content.intent;
import android.os.bundle;
import android.os.handler;
import android.os.message;
import android.view.view;
import android.view.view.onclicklistener;
import android.widget.button;
import android.widget.textview;


public class mainactivity extends activity {



 // 定义handler
 public static handler myhandler;

 // 定义intent
 private intent intent;


 // 获取控件
 private textview text_name;
 private textview text_percent;
 private button btn_start;
 private button btn_stop;


 // 文件显示
 private textview text_sel_file;


 @override
 protected void oncreate(bundle savedinstancestate) {
 // todo auto-generated method stub
 super.oncreate(savedinstancestate);
 setcontentview(r.layout.activity_main);

 

 text_name = (textview) findviewbyid(r.id.text_name);


 text_percent = (textview) findviewbyid(r.id.text_percent);

 btn_start = (button) findviewbyid(r.id.btn_start);

 btn_stop = (button) findviewbyid(r.id.btn_stop);


 

 // 按钮一的返回信息,显示进度
 myhandler = new handler() {
  @override
  public void handlemessage(message msg) {
  super.handlemessage(msg);

  if (msg.what == 0x0001) {
   bundle data = msg.getdata();
   string str = data.getstring("value");
   text_percent.settext(str);
  }
  }
 };
 // 显式的方式调用helloservice
 intent = new intent(this, downservice.class);
 // 设置启动按钮点击事件
 btn_start.setonclicklistener(new onclicklistener() {
  @override
  public void onclick(view v) {
  
  // 开启服务
  startservice(intent);
  
  }
 });
 // 设置停止按钮点击事件
 btn_stop.setonclicklistener(new onclicklistener() {
  @override
  public void onclick(view v) {
  // 关闭服务
  stopservice(intent);
  }
 });

 

 
 }

 /***
 * 被调用activity一旦返回值 该回调方法将被系统自动调用
 */
 @override
 protected void onactivityresult(int requestcode, int resultcode,
  intent intent) {
 super.onactivityresult(requestcode, resultcode, intent);
 // 如果请求码是0
 // 并且返回的结果码为1
 // 请求的activity可能返回多种结果码
 if (requestcode == 0 && resultcode == 1) {
  // 取出数据
  bundle data = intent.getextras();
  string str = data.getstring("files");
  // 显示数据
  text_sel_file.settext(str);
 }
 }

} 

3.activity_main.xml文件

 <?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >
  
  

  <linearlayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margintop="20dp"
    android:orientation="horizontal" >

    <textview
      android:id="@+id/text_name"
      android:layout_width="160dp"
      android:layout_height="wrap_content"
      android:layout_gravity="center_vertical"
      android:text="1" />

    <textview
      android:id="@+id/text_percent"
      android:layout_width="50dp"
      android:layout_height="wrap_content" 
      android:layout_gravity="center_vertical"
      android:layout_marginleft="20dp"
      android:text="0%"/>

    <linearlayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginleft="20dp"
      android:orientation="vertical" >
      <button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="start"
        />
      <button
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="stop"
        />
      
    </linearlayout>
  </linearlayout>  
</linearlayout> 

4.downservice用于在后台开启线程执行下载 

package com.xhy.zz;


import java.io.bufferedinputstream;
import java.io.bufferedreader;
import java.io.bufferedwriter;
import java.io.file;
import java.io.fileoutputstream;
import java.io.inputstreamreader;
import java.io.outputstreamwriter;
import java.io.printwriter;
import java.net.inetaddress;
import java.net.socket;
import java.net.unknownhostexception;

import android.app.service;
import android.content.context;
import android.content.intent;
import android.content.sharedpreferences;
import android.os.bundle;
import android.os.environment;
import android.os.ibinder;
import android.os.message;
import android.util.log;

public class downservice extends service {
 private static final string tag = "socket_android";

 // preferece机制操作的文件名
 public static final string preference_name = "downservice";
 // preferece机制的操作模式
 public static int mode = context.mode_private;

 // 线程
 private thread workthread;
 // 定义文件名
 private string filename="file";

 // 端口号
 private int port = 9888;

 private boolean isstop = false;

 /***
 * 必须要实现的方法
 */
 @override
 public ibinder onbind(intent intent) {
 return null;
 }

 @override
 public void oncreate() {
 super.oncreate();

 }

 @override
 public int onstartcommand(intent intent, int flags, int startid) {

 log.v("tcp", filename);
 // 建立传输的方法
 runnable backgroundwork = new runnable() {
  @override
  public void run() {

   // settitle("测试socket连接");
   socket socket = null;
   socket socket1 = null;

   try {
   /*
    * 指定server的ip地址,此地址为局域网地址,如果是使用wifi上网,则为pc机的wifi ip地址
    * 在ipconfig查看到的ip地址如下: ethernet adapter 无线网络连接:
    * connection-specific dns suffix . : ip address. . . .
    * . . . . . . . . : 192.168.155.1
    */
   inetaddress serveraddr = inetaddress
    .getbyname("192.168.155.1");// tcpserver.serverip
   log.d("tcp", "c: connecting...");
   log.d("tcp", filename + " " + port);
   // 应用server的ip和端口建立socket对象,向服务端发送请求获取文件大小的值
   socket1 = new socket(serveraddr, port);
   string message = "---test_socket_android---";

   log.d("tcp", "c: sending: '" + message + "'");

   // 将信息通过这个对象来发送给server
   printwriter out = new printwriter(new bufferedwriter(
    new outputstreamwriter(
     socket1.getoutputstream())), true);

   // 把用户输入的内容发送给server
   out.println("file_size");
   out.flush();

   // 接收服务器信息
   bufferedreader in = new bufferedreader(
    new inputstreamreader(socket1.getinputstream()));
   // 获取文件大小
   string str1 = in.readline();

   log.d("tcp", str1);
   // 将文件大小转成int型
   int sum = integer.parseint(str1);
   log.d("tcp", str1);
   // 关闭输入流
   in.close();

   sharedpreferences sharedpreferences = getsharedpreferences(
    preference_name, mode);

   sharedpreferences.editor editor = sharedpreferences
    .edit();
   //取出已经传输了的字节
   int pre = sharedpreferences.getint("downservice", 0);
   int _pre = pre;
   //将其转化为字符串以便发送给服务端
   string s = string.valueof(_pre);

   // 应用server的ip和端口建立socket对象再次向服务端发送请求,以获取文件内容
   socket = new socket(serveraddr, port);

   // 向服务端发送请求获得文件的字符
   printwriter out1 = new printwriter(
    new bufferedwriter(new outputstreamwriter(
     socket.getoutputstream())), true);

   out1.println("ok"+s);
   out1.flush();
   out.close();
   

   // 定义输入流
   bufferedinputstream bis = new bufferedinputstream(
    socket.getinputstream());

   string file1 = filename;
   string file;
   // 判断手机是否插入了sdcard,是则将文件插入内存卡
   if (environment.getexternalstoragestate().equals(
    environment.media_mounted)) {
    file sdcard = environment
     .getexternalstoragedirectory();

    // sd卡定义文件
    file = sdcard.getcanonicalfile() + "/" + file1;
    // 定义文件输出流
    fileoutputstream fos = new fileoutputstream(file,true);
    try {
    int t = -1;
    int downloaded = pre;

    // 定义每次传输的字节数
    byte[] buff = new byte[8192];
    log.i("sum", sum + "");
    // 开始将服务端的文件写入手机sd卡中
    while ((t = bis.read(buff)) != -1) {
     if (isstop == true) {
     break;
     }
     fos.write(buff, 0, t);
     downloaded += t;
     
     //将传输的进度存储起来
     editor.putint("downservice", downloaded);
     editor.commit();
     
     //当传完了则把存储信息归零
     if (downloaded == sum) {
     editor.putint("downservice", 0);
     editor.commit();
     }
     // 获得文件传输的进度
     float wb = ((downloaded * 100) / (float) sum);
     int wi = (int) wb;
     system.out.println(downloaded);
     string str = string.valueof(wi) + "%";

     // 将文件的传输进度给送给baseactivity,以显示给用户
     message msg = new message(); // 生成消息
     // 生成消息
     msg.what = 0x0001; // 设置消息类型
     // 生成bundle携带数据
     bundle data = new bundle();
     data.putstring("value", str);
     msg.setdata(data);
     // 利用handler发送消息
     mainactivity.myhandler.sendmessage(msg);

    }
    
    // 关闭输入输出流
    bis.close();
    fos.flush();
    fos.close();

    } catch (exception e) {
    bis.close();
    fos.flush();
    fos.close();
    }
   }
   log.d(tag, "from server:'已接收" + "'");
   } catch (unknownhostexception e) {
   log.e(tag, "192.168.155.1 is unkown server!");
   } catch (exception e) {
   e.printstacktrace();
   } finally {
   try {
    socket.close();
   } catch (exception e) {
    e.printstacktrace();
   }
   }

  }
  
 };
 workthread = new thread(backgroundwork);
 // isalive方法用于判断workthread线程是否被开启
 if (!workthread.isalive()) {
  // 生成新线程
  workthread.start();
  log.v("servicelife", "线程开始工作");
 } else {
  log.v("workthread", "线程已经被调用");
 }

 return start_sticky;
 }

 @override
 public void ondestroy() {

 super.ondestroy();
 // 利用interrupt方式中断该线程
 isstop = true;

 log.v("servicelife", "ondestroy方法被调用");
 }

}

5、最后别忘了注册androidmanifest.xml

 <uses-permission android:name="android.permission.internet" />
 <uses-permission android:name="android.permission.mount_unmount_filesystems" >
 </uses-permission>
 <uses-permission android:name="android.permission.write_external_storage" >
 </uses-permission>
 
 <service android:name=".downservice" ></service>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网