What is Socket?
Socket s are also called sockets. They are used to describe IP addresses and ports. They are handles for communication links. Applications usually send requests to or respond to network requests through sockets. They are abstract representations of endpoints in the process of network communication. It mainly includes the following two protocols: TCP (Transmission Control Protocol): Transmission Control Protocol, which provides connection-oriented, reliable byte stream services. Before clients and servers exchange data with each other, a TCP connection must be established between them before data can be transmitted. TCP provides functions such as overtime retransmitting, discarding duplicate data, checking data, flow control, etc. to ensure that data can be transmitted from one end to the other. UDP (User Datagram Protocl User Datagram Protocol): User Datagram Protocol is a simple transport layer protocol for datagrams. UDP does not provide reliability, it just sends data packets from the application to the IP layer, but it does not guarantee that they can reach their destination. Because UDP does not need to establish a connection between the client and the server before transferring the datagram, and there is no mechanism such as timeout and retransmit, the transmission speed of UDP is very fast.
Detailed explanations are as follows:
TCP transmission is different from UDP. TCP transmission is streaming. First, the connection must be established, and then the data stream is transmitted along the connected line (virtual circuit). Therefore, TCP data flow will not be like UDP datagrams, each datagram will contain the destination address and port, because each datagram will be routed separately. TCP transmission only needs to specify the destination address and port when establishing the connection.
In image, TCP is like making a phone call, UDP is like sending a telegram. Generally speaking, UDP does not distinguish between client and server. Both sides of the communication are equal. Microscopically speaking, there is only one message, the sender is the client, and the listener is the server. Sender sending data to router is like sending a telegram to post office. The latter thing is that sender can't control and know nothing about it. So it's unreliable. There may be missing messages and no one knows about them. Just as every telegram needs a recipient, every datagram needs a destination address and port.
TCP is divided into client and server for every connection. The initiator of the connection (comparable to the dial-up caller) is the client, and the listener (equivalent to the person waiting to answer the phone) is the server. The initiator specifies the address and port of the server to be connected (equivalent to dialing), and the listener establishes the connection by shaking hands with the initiator three times (equivalent to answering the phone when the phone rings). After establishing the connection, both sides can send and receive data (call) from each other.
How does Java operate Socket?
It is worth mentioning that Java provides corresponding classes for TCP and UDP respectively. TCP is a kind of socket and Server Socket in java. NET, which are used to represent the client and server of two-way connection respectively. These are two very well encapsulated classes. They are very convenient to use. UDP is java.Net.DatagramSocket. 127.0.0.1 is the loop address, which is used for testing. It is equivalent to the local host local address. It has no network card and can be accessed without DNS. The port address is between 0 and 65535. The port between 0 and 1023 is used for some well-known network services and applications. The user's ordinary network application should use more than 1024 ports.
The Socket communication model is as follows:
If you still have ambiguities about Java Socket programming, take a closer look at them.( http://blog.csdn.net/shimiso/article/details/8529941 This article does not elaborate on it. Let's take the most commonly used TCP protocol as an example.
Server Socket is used to listen on the specified port, which can be designated at will (since ports below 1024 are usually reserved ports and can not be used at will in some operating systems, so it is recommended to use ports larger than 1024), wait for customer connection requests, after customer connection, session is generated; after the session is completed, the connection is closed.
Client, using Java socket communication to make a connection request to a certain port of a server on the network, once the connection is successful, open the session; after the session is completed, close the Socket. Clients do not need to specify open ports, usually temporarily and dynamically allocate more than 1024 ports.
TCP network connection model:
Android client program generation analysis:
UploadActivity.java package com.android.upload; import java.io.File; import java.io.OutputStream; import java.io.PushbackInputStream; import java.io.RandomAccessFile; import java.net.Socket; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.android.service.UploadLogService; import com.android.socket.utils.StreamTool; public class UploadActivity extends Activity { private EditText filenameText; private TextView resulView; private ProgressBar uploadbar; private UploadLogService logService; private boolean start=true; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { int length = msg.getData().getInt("size"); uploadbar.setProgress(length); float num = (float)uploadbar.getProgress()/(float)uploadbar.getMax(); int result = (int)(num * 100); resulView.setText(result+ "%"); if(uploadbar.getProgress()==uploadbar.getMax()){ Toast.makeText(UploadActivity.this, R.string.success, 1).show(); } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); logService = new UploadLogService(this); filenameText = (EditText)this.findViewById(R.id.filename); uploadbar = (ProgressBar) this.findViewById(R.id.uploadbar); resulView = (TextView)this.findViewById(R.id.result); Button button =(Button)this.findViewById(R.id.button); Button button1 =(Button)this.findViewById(R.id.stop); button1 .setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { start=false; } }); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { start=true; String filename = filenameText.getText().toString(); if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ File uploadFile = new File(Environment.getExternalStorageDirectory(), filename); if(uploadFile.exists()){ uploadFile(uploadFile); }else{ Toast.makeText(UploadActivity.this, R.string.filenotexsit, 1).show(); } }else{ Toast.makeText(UploadActivity.this, R.string.sdcarderror, 1).show(); } } }); } /** * Upload files * @param uploadFile */ private void uploadFile(final File uploadFile) { new Thread(new Runnable() { @Override public void run() { try { uploadbar.setMax((int)uploadFile.length()); String souceid = logService.getBindId(uploadFile); String head = "Content-Length="+ uploadFile.length() + ";filename="+ uploadFile.getName() + ";sourceid="+ (souceid==null? "" : souceid)+"\r\n"; Socket socket = new Socket("192.168.1.78",7878); OutputStream outStream = socket.getOutputStream(); outStream.write(head.getBytes()); PushbackInputStream inStream = new PushbackInputStream(socket.getInputStream()); String response = StreamTool.readLine(inStream); String[] items = response.split(";"); String responseid = items[0].substring(items[0].indexOf("=")+1); String position = items[1].substring(items[1].indexOf("=")+1); if(souceid==null){//Add a binding record to the database instead of uploading the file. logService.save(responseid, uploadFile); } RandomAccessFile fileOutStream = new RandomAccessFile(uploadFile, "r"); fileOutStream.seek(Integer.valueOf(position)); byte[] buffer = new byte[1024]; int len = -1; int length = Integer.valueOf(position); while(start&&(len = fileOutStream.read(buffer)) != -1){ outStream.write(buffer, 0, len); length += len; Message msg = new Message(); msg.getData().putInt("size", length); handler.sendMessage(msg); } fileOutStream.close(); outStream.close(); inStream.close(); socket.close(); if(length==uploadFile.length()) logService.delete(uploadFile); } catch (Exception e) { e.printStackTrace(); } } }).start(); } } StreamTool.java package com.android.socket.utils; 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 { 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: 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 array * @throws Exception */ public static 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(); } } UploadLogService.java package com.android.service; import java.io.File; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; public class UploadLogService { private DBOpenHelper dbOpenHelper; public UploadLogService(Context context){ this.dbOpenHelper = new DBOpenHelper(context); } public void save(String sourceid, File uploadFile){ SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); db.execSQL("insert into uploadlog(uploadfilepath, sourceid) values(?,?)", new Object[]{uploadFile.getAbsolutePath(),sourceid}); } public void delete(File uploadFile){ SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); db.execSQL("delete from uploadlog where uploadfilepath=?", new Object[]{uploadFile.getAbsolutePath()}); } public String getBindId(File uploadFile){ SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); Cursor cursor = db.rawQuery("select sourceid from uploadlog where uploadfilepath=?", new String[]{uploadFile.getAbsolutePath()}); if(cursor.moveToFirst()){ return cursor.getString(0); } return null; } } DBOpenHelper.java package com.android.service; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DBOpenHelper extends SQLiteOpenHelper { public DBOpenHelper(Context context) { super(context, "upload.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE uploadlog (_id integer primary key autoincrement, uploadfilepath varchar(100), sourceid varchar(10))"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS uploadlog"); onCreate(db); } } 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" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/filename" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="022.jpg" android:id="@+id/filename" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button" android:id="@+id/button" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="suspend" android:id="@+id/stop" /> <ProgressBar android:layout_width="fill_parent" android:layout_height="20px" style="?android:attr/progressBarStyleHorizontal" android:id="@+id/uploadbar" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/result" /> </LinearLayout> AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.upload" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".UploadActivity" 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> <!-- Access to the network --> <uses-permission android:name="android.permission.INTERNET"/> <!-- stay SDCard Create and delete file permissions in --> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <!-- to SDCard Write data permissions --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> </manifest>
Java server:
SocketServer.javapackage com.android.socket.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.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.android.socket.utils.StreamTool; public class SocketServer { private String uploadPath="D:/uploadFile/"; private ExecutorService executorService;// Thread pool private ServerSocket ss = null; private int port;// Monitor port private boolean quit;// Whether to quit private Map<Long, FileLog> datas = new HashMap<Long, FileLog>();// Store breakpoint data, it is better to change to data storage public SocketServer(int port) { this.port = port; // Initialize thread pool executorService = Executors.newFixedThreadPool(Runtime.getRuntime() .availableProcessors() * 50); } // Startup service public void start() throws Exception { ss = new ServerSocket(port); while (!quit) { Socket socket = ss.accept();// Accept client requests // To support multi-user concurrent access, thread pool is used to manage the connection requests of each user. executorService.execute(new SocketTask(socket));// Start a thread to process requests } } // Sign out public void quit() { this.quit = true; try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { SocketServer server = new SocketServer(7878); server.start(); } private class SocketTask implements Runnable { private Socket socket; public SocketTask(Socket socket) { this.socket = socket; } @Override public void run() { try { System.out.println("accepted connenction from " + socket.getInetAddress() + " @ " + socket.getPort()); PushbackInputStream inStream = new PushbackInputStream( socket.getInputStream()); // Get the first line of protocol data from the client: Content-Length = 143253434; filename = xxxx.3gp; sourceid= // If the user uploads the file for the first time, the value of sourceid is empty. String head = StreamTool.readLine(inStream); System.out.println(head); if (head != null) { // Next, read the various parameter values from the protocol data 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(); FileLog log = null; if (null != sourceid && !"".equals(sourceid)) { id = Long.valueOf(sourceid); log = find(id);//Find if the uploaded file has an upload record } File file = null; int position = 0; if(log==null){//If the uploaded file does not have an upload record, add a trace record to the file String path = new SimpleDateFormat("yyyy/MM/dd/HH/mm").format(new Date()); File dir = new File(uploadPath+ path); if(!dir.exists()) dir.mkdirs(); file = new File(dir, filename); if(file.exists()){//If the uploaded file is renamed, it is renamed filename = filename.substring(0, filename.indexOf(".")-1)+ dir.listFiles().length+ filename.substring(filename.indexOf(".")); file = new File(dir, filename); } save(id, file); }else{// If the uploaded file has an upload record, read the last breakpoint location file = new File(log.getPath());//The path to get the file from the upload record if(file.exists()){ File logFile = new File(file.getParentFile(), file.getName()+".log"); if(logFile.exists()){ Properties properties = new Properties(); properties.load(new FileInputStream(logFile)); position = Integer.valueOf(properties.getProperty("length"));//Read breakpoint position } } } OutputStream outStream = socket.getOutputStream(); String response = "sourceid="+ id+ ";position="+ position+ "\r\n"; //When the server receives the request information from the client, it returns the response information to the client: sourceid=1274773833264;position=0. //Sorceid is generated by the service and uniquely identifies the uploaded file. position indicates where the client starts uploading the file. outStream.write(response.getBytes()); RandomAccessFile fileOutStream = new RandomAccessFile(file, "rwd"); if(position==0) fileOutStream.setLength(Integer.valueOf(filelength));//Setting File Length fileOutStream.seek(position);//Start writing data at the location specified by the mobile file byte[] buffer = new byte[1024]; int len = -1; int length = position; while( (len=inStream.read(buffer)) != -1){//Read and write data from input stream to file fileOutStream.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);//The Last Storage Location of Real-time Recording Files logFile.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 upload records public void save(Long id, File saveFile) { // In the future, it can be stored through the database. datas.put(id, new FileLog(id, saveFile.getAbsolutePath())); } // When the file is uploaded, delete the record 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) { super(); 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; } } } ServerWindow.javapackage com.android.socket.server; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.Label; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; public class ServerWindow extends Frame{ private SocketServer server; private Label label; public ServerWindow(String title){ super(title); server = new SocketServer(7878); label = new Label(); add(label, BorderLayout.PAGE_START); label.setText("The server has been started"); this.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { new Thread(new Runnable() { @Override public void run() { try { server.start(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { server.quit(); System.exit(0); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { } }); } /** * @param args */ public static void main(String[] args) { ServerWindow window = new ServerWindow("File upload server"); window.setSize(300, 300); window.setVisible(true); } } StreamTool.javapackage com.android.socket.utils; 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 { 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: 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 array * @throws Exception */ public static 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(); } }
The operation results are as follows:
Android front-end control: