This article describes how to use a thread pool to create a socket service and support resumable data transfer for large files.
First, create a tool class:
Package COM. android. server. util; import Java. io. bytearrayoutputstream; import Java. io. file; import Java. io. fileoutputstream; import Java. io. ioexception; import Java. io. inputstream; import Java. io. pushbackinputstream; public class streamtool {/*** save the file ** @ Param file * file path * @ Param data * bytecode data * @ throws exception */public static void save (File file, byte [] data) throws exception {fileoutputstream fileo Utputstream = new fileoutputstream (File); fileoutputstream. write (data); fileoutputstream. close ();}/*** read a line * @ Param in input stream * @ return escape * @ throws ioexception */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: Case '\ N': Break loop; Case' \ R': int C2 = in. Read (); If (C2! = '\ N' & 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 Count * @ throws exception */public static byte [] readstream (inpu Tstream instream) throws exception {bytearrayoutputstream outputstream = new bytearrayoutputstream (); byte [] Buf = new byte [1024]; int Len =-1; while (LEN = instream. read (BUF ))! = 1) {outputstream. Write (BUF, 0, Len) ;}outputstream. Close (); instream. Close (); Return outputstream. tobytearray ();}}
This tool class is mainly used to read and write files.
Next let's take a look at how to write this socket
See the Code:
Package COM. android. server; import Java. io. file; import Java. io. fileinputstream; import Java. io. fileoutputstream; import Java. io. ioexception; import Java. io. outputstream; import Java. io. pushbackinputstream; import Java. io. randomaccessfile; import java.net. serversocket; import java.net. socket; import Java. text. simpledateformat; import Java. util. date; import Java. util. hashmap; import Java. util. map; import Java. UTI L. properties; import Java. util. concurrent. executorservice; import Java. util. concurrent. executors; import COM. android. server. util. streamtool; public class socketserver {private executorservice; // thread pool private serversocket Server = NULL; private int port; // listen to private Boolean quit; // whether to exit the private Map <long, filelog> datas = new hashmap <long, filelog> (); // store the breakpoint data public socketserver (INT port) {This. port = port; // initialize the thread pool executorservice = executors. newfixedthreadpool (runtime. getruntime (). availableprocessors () * 50); // obtain the CPU category, the more threads the CPU gets} public void start () throws ioexception {Server = new serversocket (port ); while (! Quit) {Socket socket = server. accept (); // accept the request to the client executorservice.exe cute (New sockettask (socket); // use the thread pool to manage user concurrency} public void quit () {This. quit = true; try {server. close ();} catch (exception e) {e. printstacktrace () ;}} private class sockettask implements runnable {private Socket socket; Public sockettask (Socket socket) {This. socket = socket ;}@ overridepublic void run () {try {system. out. println ("accepted con Nection from "+ socket. getinetaddress () + "@" + socket. getport (); pushbackinputstream inputstream = new pushbackinputstream (socket. getinputstream (); // obtain the number of the first row sent by the Client: Content-Length = 143253434; filename = xxx.3gp; sourceid = // if the first request sourceid is empty string head = streamtool. readline (inputstream); system. out. println (head); If (Head! = NULL) {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 (); // file idfilelog log = NULL; If (null! = Sourceid &&! "". Equals (sourceid) {id = long. valueof (sourceid); log = find (ID); // query whether an upload record exists in a file} file = NULL; // The saved file int position = 0; // breakpoint location // If the uploaded file does not have an upload record, add a tracking record for the file if (log = NULL) {string Path = new simpledateformat ("yyyy/mm/DD/hh/MM/SS "). format (new date (); file dir = new file ("file/" + path); If (! Dir. exists () dir. mkdirs (); file = new file (Dir, filename); // create an upload file if (file. exists () {// if the file exists, rename it filename = filename. substring (0, filename. indexof (". ") + dir. listfiles (). length + filename. substring (filename. indexof (". "); file = new file (Dir, filename);} Save (ID, file);} else {// if a file breakpoint exists, read the last file = new file (log. getpath (); If (file. exists () {file logfile = new file (file. getparentfile (), file. getnam E () + ". log "); If (logfile. exists () {properties Properties = new properties (); properties. load (New fileinputstream (logfile); position = integer. valueof (properties. getproperty ("length"); // location where the breakpoint is read }}// the server receives the request from the client and sends the corresponding information to the client: sourceid, and position information outputstream = socket. getoutputstream (); string respons = "sourceid =" + ID + "position" + Position + "\ r \ n"; outputstream. write (respons. getbyte S (); randomaccessfile accessfile = new randomaccessfile (file, "RWD"); If (position = 0) accessfile. setlength (integer. valueof (filelength); // sets the file length accessfile. seek (position); // move to the specified position to write data byte [] Buf = new byte [1024]; int Len = 1; int length = position; while (LEN = inputstream. read (BUF ))! =-1) {accessfile. write (BUF, 0, Len); Length + = Len; properties Properties = new properties (); properties. put ("length", String. valueof (length); fileoutputstream = new fileoutputstream (new file (file. getparent (), file. getname () + ". log "); properties. store (fileoutputstream, null); // records the last storage location of the file in real time. close ();} If (length = accessfile. length () Delete (ID); accessfile. close (); inputstream. close (); Outputstream. Close () ;}} catch (exception e) {} finally {If (socket! = NULL &&! Socket. isclosed () Try {socket. close ();} catch (ioexception e) {// todo auto-generated catch blocke. printstacktrace () ;}}} public static void main (string [] ARGs) {string S = "12345"; system. out. println (S. indexof ("5"); system. out. println (S. substring (2, S. indexof ("5");}/*** find file ** @ Param sourceid * File ID * @ return */Public filelog find (long sourceid) {return datas. get (sourceid);}/*** save file breakpoint ** @ Param ID * File ID * @ Param file */Public void save (long ID, file) {datas. put (ID, new filelog (ID, file. getabsolutepath ();}/*** the breakpoint for deleting a file record after the file goes to bed ** @ Param sourceid * File ID */Public void Delete (long sourceid) {If (datas. containskey (sourceid) {datas. remove (sourceid) ;}} private class filelog {private long ID; private string path; Public filelog (long ID, string path) {This. id = ID; this. path = 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 ;}}}
We use a map object to store the breakpoint location of the file, so that the next upload can be resumed. Executorservice thread pool is used to manage our sockettask threads. Filelog is the class for uploading and storing each file!
Now we have completed a simple resumable upload service.