Android深入淺出系列之Socket—Socket編程

一:什么是Socket    
    它實際上是網(wǎng)絡(luò)通信的一種接口,基于不同的協(xié)議,有各種不同的Socket,比如有基于TCP協(xié)議的Socket和基于UDP協(xié)議的Socket以及基于藍牙協(xié)議的Socket,Android中使用的是Java的Socket模型。
    Socket在計算機行業(yè)通常稱為”套接字“,用于描述IP地址和端口,是一個通信鏈的句柄。這是一個比較抽象的概念。計算機是擁有端口的,每一個端口都可以有一個應(yīng)用程序來進行通訊的使用,比如:80端口是HTTP協(xié)議所使用的端口,21端口是FTP協(xié)議所使用的端口,端口是計算機和外界通訊的接口,這些接口都是邏輯的接口,端口號取值的范圍是零到256乘以256減1,1024以下的端口都是操作系統(tǒng)使用的保留端口,以上的端口我們可以自由的來使用,不要和其他應(yīng)用程序的端口沖突。
    應(yīng)用程序可以通過“套接字”向網(wǎng)絡(luò)發(fā)送請求或者應(yīng)答網(wǎng)絡(luò)的請求,這時候就把Socket分成了兩部分,一部分是服務(wù)器端的Socket,這個Socket主要用來接收來自網(wǎng)絡(luò)的請求,它一直監(jiān)聽在某一個端口上。一部分是客戶端的Socket,這個Socket主要用來向網(wǎng)絡(luò)發(fā)送數(shù)據(jù)。
  二:Socket通訊模型

  

    -UDP協(xié)議和TCP協(xié)議
    UDP協(xié)議和TCP協(xié)議是互聯(lián)網(wǎng)使用最廣的兩種協(xié)議都是基于IP的協(xié)議。第一個區(qū)別是UDP協(xié)議是一個不太靠譜的協(xié)議,UDP協(xié)議把數(shù)據(jù)都打成數(shù)據(jù)包,數(shù)據(jù)包上自帶通訊地址,也就是說我要把這個數(shù)據(jù)包發(fā)送到網(wǎng)絡(luò)上的哪一個地址,通過網(wǎng)絡(luò)把這個數(shù)據(jù)包發(fā)送出去,至于這個數(shù)據(jù)包是否發(fā)送到目的地,是否服務(wù)器端接收到了這個數(shù)據(jù)包,這個協(xié)議并不保證,就像中國的郵政,你是把信寄出去了,但是郵政系統(tǒng)不保證對方能收到你寄送的信。TCP發(fā)送數(shù)據(jù)的時候要求接收方接收到數(shù)據(jù)之后給一個回應(yīng),也就是你是否收到了,TCP可靠一些,當(dāng)我們發(fā)送一些比較重要的數(shù)據(jù)的時候一般都使用TCP協(xié)議。另外一個區(qū)別是UDP協(xié)議發(fā)送的一個數(shù)據(jù)包它的容量是有限的,而TCP協(xié)議則沒有這樣一個限制。并不是說UDP協(xié)議一定就不如TCP協(xié)議,在不同的領(lǐng)域有不同是使用,UDP協(xié)議好處是速度相對快些。TCP協(xié)議相對慢些。
    -Socket通訊流程
    應(yīng)用程序通過“套接字”也就是Socket可以選擇這兩種協(xié)議當(dāng)中的一種,你可以選擇用UDP發(fā)送數(shù)據(jù),也可以選擇用TCP發(fā)送數(shù)據(jù),數(shù)據(jù)發(fā)送出去通過“通信信道”也就是IP的基礎(chǔ)網(wǎng)絡(luò),來到服務(wù)器端(接收端),就可以接收到數(shù)據(jù)了。發(fā)送數(shù)據(jù)的時候用UDP協(xié)議,接收的時候也要用UDP協(xié)議,發(fā)送數(shù)據(jù)的時候用TCP協(xié)議,接收的時候也要用TCP協(xié)議,在發(fā)送的時候指定接收端的IP地址和端口號就可以了,究竟數(shù)據(jù)包或數(shù)據(jù)是如何發(fā)送的,框架已經(jīng)幫我們封裝好了,我們不去關(guān)心它了。

這篇博文介紹基于TCP協(xié)議來進行數(shù)據(jù)的發(fā)送,通常用于發(fā)送文件采用這種方式。
  一:TCP協(xié)議通訊模型
    1:工作流程

    

    首先有兩部分客戶端和服務(wù)器端,客戶端需要Socket這個類的對象,而服務(wù)器端需要ServerSocket這個類的對象,由客戶端Socket發(fā)送一個請求,服務(wù)器端的ServerSocket在計算機的某一個端口號上進行監(jiān)聽,監(jiān)聽客戶端發(fā)送的請求之后,那么客戶端和服務(wù)器端的一個通訊通道就建立起來了,這時候呢既可以從客戶端向服務(wù)器端發(fā)送數(shù)據(jù),服務(wù)器端也可以給客戶端相應(yīng)的響應(yīng)。在客戶端發(fā)送數(shù)據(jù)的時候我們需要用到IO流里面的OutputStream,通過這個OutputStream把數(shù)據(jù)發(fā)送給服務(wù)器端,服務(wù)器端用InputStream來讀取客戶端當(dāng)中用OutputStream所寫入的數(shù)據(jù)。生活舉例:就像雙方男女朋友打電話一樣,男孩(客戶端)說話(數(shù)據(jù))通過聽筒發(fā)送到電話網(wǎng)絡(luò)中去,當(dāng)男孩說話的時候就相當(dāng)于咱們這里的通過OutputStream向互聯(lián)網(wǎng)中寫入數(shù)據(jù),而作為接聽的這個女孩(服務(wù)器端)那么男孩(客戶端)說的內(nèi)容就是女孩(服務(wù)器端)聽到的內(nèi)容,那么就是說服務(wù)器端可以通過InputStream把客戶端當(dāng)中通過OutputStream所寫入的數(shù)據(jù)給它讀取出來,反之亦然,如果服務(wù)器端想向客戶端發(fā)送數(shù)據(jù),那么就使用OutputStream寫出數(shù)據(jù),在客戶端通過InputStream把服務(wù)器端當(dāng)中通過OutputStream所寫入的數(shù)據(jù)給它讀取出來。就像打電話一樣,你說的就是我聽的,你聽的就是我說的。
  二:通過基于TCP協(xié)議發(fā)送和讀取數(shù)據(jù)
1:布局文件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">
   <Button
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="啟動監(jiān)聽線程"
     android:id="@+id/btn1"/>
    </LinearLayout>

2.1:服務(wù)器端Socket代碼文件MainActivity.java

package com.szy.socket;
      import android.app.Activity;
      import android.os.Bundle;
      import android.util.Log;
      import android.view.View;
      import android.view.View.OnClickListener;
      import android.widget.Button;
      import java.io.IOException;
      import java.io.InputStream;
      import java.net.ServerSocket;
      import java.net.Socket;

public class MainActivity extends Activity
      {
         private Button btn1 = null;

       @Override

public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          btn1 = (Button) findViewById(R.id.btn1);
          btn1.setOnClickListener(new Btn1Listener());
        }

       private class Btn1Listener implements OnClickListener{

@Override
           public void onClick(View v){
            new ServerThread().start();
          }
       }

private class ServerThread extends Thread
      {
        public void run()
         {
          ServerSocket serverSocket = null;
          try{
             serverSocket = new ServerSocket(4567);
            Socket socket = serverSocket.accept();
            InputStream inputStream = socket.getInputStream();
             byte data[] = new byte[1024*4];
             int i = 0;
            while((i = inputStream.read(data)) !=1 )
              Log.d("mytag",new String(data,0,i));
           }catch (IOException e){
            e.printStackTrace();
           }
           finally{
            try{
              serverSocket.close();
            } catch (IOException e){
              e.printStackTrace();
            }
          }
      }
    }
    }
2.2:客戶端Socket代碼文件TcpSocketClient.java
  
  package com.szy.socketclient;
      import android.app.Activity;
      import java.net.Socket;
      import java.io.FileInputStream;
      import java.io.InputStream;
      import java.io.OutputStream;

public class TcpSocketClient extends Activity
      {
        public static void main(String[] args)
        {
          try{
            Socket socket = new Socket("192.168.1.105",4567);
            InputStream inputStream = new FileInputStream("C://www.txt");
            OutputStream outputStream = socket.getOutputStream();
            byte data[] = new byte[1024*4];
            int i = 0;
            while((i = inputStream.read(data)) !=1 ){
              outputStream.write(data, 0, i);
}
            outputStream.flush();
         } catch (Exception e){
           e.printStackTrace();
}
        }
      }
    }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容