Basic tutorial for Android -- 7.6.3 Socket communication based on TCP protocol (2)

Source: Internet
Author: User
Tags manage connection

Basic tutorial for Android -- 7.6.3 Socket communication based on TCP protocol (2)
This section introduces:

In the previous section, we introduced some basic concepts and usage of Socket, and then wrote a simple chat room for piggy
Demo, I believe you have a preliminary understanding of the Socket. In this section, we will learn how to use the Socket to achieve resumable upload of large files!
The following is an example of uploading large files through a Socket written by someone else. We do not need to write this file by ourselves.
Good!

1. Run:

1. Run the compiled Socket server first:

2. Put an audio file under the root directory of the SD card:

3. Run our client:

4. After the upload is successful, we can see that a file folder is generated under the project on our server side. Here we can find the uploaded file:
. Log that is our log file

2. implementation flowchart:

3. Sample Code:

First, write a stream parsing class used by both the server and client:

StreamTool. java:

Public class StreamTool {public static void save (File file, byte [] data) throws Exception {FileOutputStream outStream = new FileOutputStream (file); outStream. write (data); outStream. close ();} public static String readLine (PushbackInputStream in) throws IOException {char buf [] = new char [128]; int room = buf. length; int offset = 0; int c; loop: while (true) {switch (c = in. read () {case-1: cas E '': break loop; case'': int c2 = in. read (); if (c2! = '') & (C2! =-1) in. unread (c2); break loop; default: if (-- room <0) {char [] lineBuffer = buf; buf = new char [offset + 128]; room = buf. length-offset-1; System. arraycopy (lineBuffer, 0, buf, 0, offset);} buf [offset ++] = (char) c; break ;}} if (c =-1) & (offset = 0) return null; return String. copyValueOf (buf, 0, offset);}/*** read stream * @ param inStream * @ return byte array * @ throws Exception */public st Atic byte [] readStream (InputStream inStream) throws Exception {ByteArrayOutputStream outSteam = new ByteArrayOutputStream (); byte [] buffer = new byte [1024]; int len =-1; while (len = inStream. read (buffer ))! =-1) {outSteam. write (buffer, 0, len);} outSteam. close (); inStream. close (); return outSteam. toByteArray ();}}
1) server implementation:

Socket management and multi-thread management:

FileServer. java:

Public class FileServer {private ExecutorService executorService; // thread pool private int port; // listener port private boolean quit = false; // exit private ServerSocket server; private Map
  
   
Datas = new HashMap
   
    
(); // Store the breakpoint data public FileServer (int port) {this. port = port; // create a thread pool. The pool has (cpu x 50) threads executorService = Executors. newFixedThreadPool (Runtime. getRuntime (). availableProcessors () * 50);}/*** quit */public void quit () {this. quit = true; try {server. close ();} catch (IOException e) {}}/*** start service * @ throws Exception */public void start () throws Exception {server = new ServerSocket (port); while (! Quit) {try {Socket socket = server. accept (); // to support concurrent access by multiple users, the thread pool is used to manage connection requests of each user executorService.exe cute (new SocketTask (socket);} catch (Exception e) {// e. printStackTrace () ;}} private final class SocketTask implements Runnable {private Socket socket = null; public SocketTask (Socket socket) {this. socket = socket;} public void run () {try {System. out. println (accepted connection + socket. getIne TAddress () +: + socket. getPort (); PushbackInputStream inStream = new PushbackInputStream (socket. getInputStream (); // obtain the first line of protocol data sent from the client: Content-Length = 143253434; filename = xxx.3gp; sourceid = // if the user uploads a file for the first time, the value of sourceid is null. String head = StreamTool. readLine (inStream); System. out. println (head); if (head! = Null) {// extract the parameter values from the protocol data below String [] items = head. split (;); String filelength = items [0]. substring (items [0]. indexOf (=) + 1); String filename = items [1]. substring (items [1]. indexOf (=) + 1); String sourceid = items [2]. substring (items [2]. indexOf (=) + 1); long id = System. currentTimeMillis (); // production resource id. to be unique, use UUID FileLog log = null; if (sourceid! = Null &&!. Equals (sourceid) {id = Long. valueOf (sourceid); log = find (id); // find whether the uploaded File has an upload record} file File = null; int position = 0; if (log = null) {// if no upload record exists, add the trail record String path = new SimpleDateFormat (yyyy/MM/dd/HH/mm) to the file ). format (new Date (); File dir = new File (file/+ path); if (! Dir. exists () dir. mkdirs (); file = new File (dir, filename); if (file. exists () {// If the uploaded file has a duplicate name, rename it filename = filename. substring (0, filename. indexOf (.) -1) + dir. listFiles (). length + filename. substring (filename. indexOf (.)); file = new File (dir, filename);} save (id, file);} else {// If an upload record exists, read the uploaded data length file = new File (log. getPath (); // obtain the file path from the upload record if (file. exists () {File logFile = new File (file. getPa Upload file (), file. getName () +. log); if (logFile. exists () {Properties properties = new Properties (); properties. load (new FileInputStream (logFile); position = Integer. valueOf (properties. getProperty (length); // read the length of uploaded data }}outputstream outStream = socket. getOutputStream (); String response = sourceid = + id +; position = + position +; // After the server receives the request information from the client, it returns the response to the client: sourceid = 1274773833264; position = 0 // sour The ceid is generated by the server and uniquely identifies the file to be uploaded. position indicates the position of the client starting from where the file is uploaded. write (response. getBytes (); RandomAccessFile fileOutStream = new RandomAccessFile (file, rwd); if (position = 0) fileOutStream. setLength (Integer. valueOf (filelength); // sets the file length fileOutStream. seek (position); // specify the bytes [] buffer = new byte [1024]; int len =-1; int length = position; while (len = inStream. read (buffer ))! =-1) {// read data from the input stream and write it to fileOutStream in the file. write (buffer, 0, len); length + = len; Properties properties = new Properties (); properties. put (length, String. valueOf (length); FileOutputStream logFile = new FileOutputStream (new File (file. getParentFile (), file. getName () +. log); properties. store (logFile, null); // records the length of the received file in real time. close ();} if (length = fileOutStream. length () delete (id); fileOutStream. close (); InStream. close (); outStream. close (); file = null ;}} catch (Exception e) {e. printStackTrace ();} finally {try {if (socket! = Null &&! Socket. isClosed () socket. close () ;}catch (IOException e) {}}} public FileLog find (Long sourceid) {return datas. get (sourceid);} // save the upload record public void save (Long id, File saveFile) {// you can change it to the database to store datas. put (id, new FileLog (id, saveFile. getAbsolutePath ();} // when the file is uploaded, delete the public void delete (long sourceid) {if (datas. containsKey (sourceid) datas. remove (sourceid);} private class FileLog {private Long id; private String path; public Long getId () {return id;} public void setId (Long id) {this. id = id;} public String getPath () {return path;} public void setPath (String path) {this. path = path;} public FileLog (Long id, String path) {this. id = id; this. path = path ;}}}
   
  

Server interface:ServerWindow. java:

Public class ServerWindow extends Frame {private FileServer s = new FileServer (12345); private Label label; public ServerWindow (String title) {super (title); Label = new Label (); add (label, BorderLayout. PAGE_START); label. setText (the server has been started); this. addWindowListener (new WindowListener () {public void windowOpened (invalid wevent e) {new Thread (new Runnable () {public void run () {try {s. start ();} catch (Exception e) {// e. printStackTrace ();}}}). start ();} public void protected wiconified (protected wevent e) {} public void windowDeiconified (protected wevent e) {} public void windowDeactivated (protected wevent e) {} public void windowClosing (protected wevent e) {s. quit (); System. exit (0);} public void windowClosed (WindowEvent e) {} public void windowActivated (WindowEvent e ){}});} /*** @ param args */public static void main (String [] args) throws IOException {InetAddress address = InetAddress. getLocalHost (); ServerWindow window = new ServerWindow (File Upload server: + address. getHostAddress (); window. setSize (400,300); window. setVisible (true );}}
2) client (Android)

First, layout files:Activity_main.xml:


  
      
       
    
     
    
   
      
       
      
    
   

For resumable upload, we need to save the upload progress and use the database. Here we define a database
Management class:DBOpenHelper. java::

/** * Created by Jay on 2015/9/17 0017. */public class DBOpenHelper extends SQLiteOpenHelper {    public DBOpenHelper(Context context) {        super(context, jay.db, null, 1);    }    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(CREATE TABLE IF NOT EXISTS uploadlog (_id integer primary key autoincrement, path varchar(20), sourceid varchar(20)));    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {    }}

Then the database operation class:UploadHelper. java:

/** * Created by Jay on 2015/9/17 0017. */public class UploadHelper {    private DBOpenHelper dbOpenHelper;    public UploadHelper(Context context) {        dbOpenHelper = new DBOpenHelper(context);    }    public String getBindId(File file) {        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();        Cursor cursor = db.rawQuery(select sourceid from uploadlog where path=?, new String[]{file.getAbsolutePath()});        if (cursor.moveToFirst()) {            return cursor.getString(0);        }        return null;    }    public void save(String sourceid, File file) {        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();        db.execSQL(insert into uploadlog(path,sourceid) values(?,?),                new Object[]{file.getAbsolutePath(), sourceid});    }    public void delete(File file) {        SQLiteDatabase db = dbOpenHelper.getWritableDatabase();        db.execSQL(delete from uploadlog where path=?, new Object[]{file.getAbsolutePath()});    }}

By the way, don't forget the stream parsing class that the client will also post. Finally, ourMainActivity. javaNow:

Public class MainActivity extends AppCompatActivity implements View. onClickListener {private EditText edit_fname; private Button listener; private Button btn_stop; private ProgressBar pgbar; private TextView txt_result; private UploadHelper upHelper; private boolean flag = true; private Handler handler = new Handler () {@ Override public void handleMessage (Message msg) {pgbar. setProgress (msg. get Data (). getInt (length); float num = (float) pgbar. getProgress ()/(float) pgbar. getMax (); int result = (int) (num * 100); txt_result.setText (result + %); if (pgbar. getProgress () = pgbar. getMax () {Toast. makeText (MainActivity. this indicates that the upload is successful, Toast. LENGTH_SHORT ). show () ;}};@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activi Ty_main); bindViews (); upHelper = new UploadHelper (this);} private void bindViews () {edit_fname = (EditText) findViewById (R. id. edit_fname); btn_upload = (Button) findViewById (R. id. btn_upload); btn_stop = (Button) findViewById (R. id. btn_stop); pgbar = (ProgressBar) findViewById (R. id. pgbar); txt_result = (TextView) findViewById(R.id.txt _ result); btn_upload.setOnClickListener (this); btn_stop.setOnCl IckListener (this) ;}@ Override public void onClick (View v) {switch (v. getId () {case R. id. btn_upload: String filename = edit_fname.getText (). toString (); flag = true; if (Environment. getExternalStorageState (). equals (Environment. MEDIA_MOUNTED) {File file = new File (Environment. getExternalStorageDirectory (), filename); if (file. exists () {pgbar. setMax (int) file. length (); uploadFile (file);} el Se {Toast. makeText (MainActivity. this, the file does not exist ~, Toast. LENGTH_SHORT ). show () ;}} else {Toast. makeText (MainActivity. this: the SD card does not exist or is unavailable. Toast. LENGTH_SHORT ). show ();} break; case R. id. btn_stop: flag = false; break;} private void uploadFile (final File file) {new Thread (new Runnable () {public void run () {try {String sourceid = upHelper. getBindId (file); Socket socket = new Socket (172.16.2.54, 12345); OutputStream outStream = socket. getOutputSt Ream (); String head = Content-Length = + file. length () +; filename = + file. getName () +; sourceid = + (sourceid! = Null? Sourceid:) +; outStream. write (head. getBytes (); PushbackInputStream inStream = new PushbackInputStream (socket. getInputStream (); String response = StreamTool. readLine (inStream); String [] items = response. split (;); String responseSourceid = items [0]. substring (items [0]. indexOf (=) + 1); String position = items [1]. substring (items [1]. indexOf (=) + 1); if (sourceid = null) {// if the file is uploaded for the first time, it does not exist in the Database Specified resource id upHelper. save (responseSourceid, file);} RandomAccessFile fileOutStream = new RandomAccessFile (file, r); fileOutStream. seek (Integer. valueOf (position); byte [] buffer = new byte [1024]; int len =-1; int length = Integer. valueOf (position); while (flag & (len = fileOutStream. read (buffer ))! =-1) {outStream. write (buffer, 0, len); length + = len; // accumulate the length of the uploaded data Message msg = new Message (); msg. getData (). putInt (length, length); handler. sendMessage (msg);} if (length = file. length () upHelper. delete (file); fileOutStream. close (); outStream. close (); inStream. close (); socket. close ();} catch (Exception e) {Toast. makeText (MainActivity. this, upload exception ~, Toast. LENGTH_SHORT). show () ;}}). start ();}}

By the way, rememberAndroidManifest. xmlWrite these permissions!

    
      
      
       
       
        
    
   
  
4. Download the Code:

Socket upload large file demo

5. Summary in this section:

This section describes another example of a TCP-based Socket: Use a Socket to resume the upload of large files,
I believe you have a better understanding of Socket. Well, let's write another example in the next section. The two are on the same Wi-Fi network.
Next, let's transfer data between the mobile phones! That's all. Thank you ~

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.