android 通信之Socket


        基於android的Socket通信

一、Socket簡介:

1.1 Android與服務器的通信方式主要有兩種,一是Http通信,一是Socket通信。兩者最大差異在於:

        Http: 使用的是“請求—響應方式”,即在請求時建立連接通道,當客戶端向服務器發送請求后,服務器端才能向客戶端返回數據。
        Socket: 在雙方建立起連接后就可以直接進行數據的傳輸,在連接時可實現信息的主動推送,而不需要每次由客戶端想服務器發送請求。

1.2 通俗理解:Socket(套接字)可以看成是兩個網絡應用程序進行通信時,各自通信連接中的端點,這是一個邏輯上的概念。
                        Socket是應用層與傳輸層的一個抽象,將復雜的TCP/IP協議隱藏在Socket接口之后,只對用戶暴露簡單的接口。
1.3 表示方法:socket=(IP地址:端口號)
1.4 主要類型(根據底層不同的協議):a.流套接字(SOCK_STREAM)基於Tcp傳輸;b.數據報套接字(SOCK_DGRAM)基於udp傳輸;

   c.原始套接字(SOCK_RAW)原始套接字可以讀寫內核沒有處理的IP數據包,而流套接字只能讀取TCP協議的數據,數據報套接字只能讀取UDP協議的數據。
       因此,如果要訪問其他協議發送的數據必須使用原始套接
1.5 基本通信模型如下圖:

 其中針對TCP socket通信通過,inputstream/outputstream進行流讀取和寫入。UDP經過datagram進行數據包的收發。

 二、Socket在android中的應用。

2.1 服務器端首先聲明一個ServerSocket對象並且指定端口號,然后調用Serversocket的accept()方法接收客戶端的數據。
accept()方法在沒有數據進行接收的處於堵塞狀態。(Socket socket=serversocket.accept()),一旦接收到數據,
通過inputstream讀取接收的數據。
客戶端創建一個Socket對象,指定服務器端的ip地址和端口號(Socket socket=newSocket("172.168.10.108",8080);),
通過inputstream讀取數據,獲取服務器發出的數據(OutputStream outputstream=socket.getOutputStream()),
最后將要發送的數據寫入到outputstream即可進行TCP協議的socket數據傳輸。


2.2 通過如下demo 模擬socket在客戶端的使用:

      2.2.1 在manifest進行權限聲明,此處用的路由局域網。

<uses-permission android:name="android.permission.INTERNET" /> 

2.2.2 使用TCP通信,界面布局做一簡單布置,不做過多介紹,界面只有有一button,來啟動客戶端和服務器兩個線程,客戶端寫入的內容,將在服務端進行解析,后handler發送 在ui的TextView中顯示。UI如下:
public class MainActivity<countClient> extends AppCompatActivity { TextView textView; EditText editText; Button bt; String tag = this.toString(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt = (Button) findViewById(R.id.bt); textView = (TextView) findViewById(R.id.textV); bt.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { new ServiceThread().start();//啟動服務器 new ClientThread().start();//啟動客戶端 } } ); }
public Handler mHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 100:
if(msg.obj == null) return;
Log.d(tag,"service receive..msg:" + msg.obj.toString());
textView.append(msg.obj.toString());
break;
}
}
};

   

2.2.3.客戶端代碼如下:

    public int countClient = 0;
    class ClientThread extends Thread {
        Socket mSocket = null;
        @Override
        public void run() {
            try {
                Log.d(tag,"ClientThread");
                mSocket = new Socket(/*"172.16.99.105"*/InetAddress.getLocalHost(), 9001);//鏈接服務器地址,端口9001.在使用此ip時可以先進行ping
                Log.d(tag,"InetAddress.getLocalHost:" + InetAddress.getLocalHost());
                OutputStream outputStream = mSocket.getOutputStream();
                PrintWriter pw = new PrintWriter(outputStream);
                countClient ++;
                pw.write("客戶端給服務器端發送的數據"+countClient);
                pw.flush();
                //關閉輸出流
                mSocket.shutdownOutput();
                pw.close();
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
                Log.d(tag,"Client IOExcept..e: " + e);
            }
        }
    }

2.2.4.服務端代碼如下:

class ServiceThread extends Thread {
        ServerSocket mServiceSocket = null;
        Socket mSocket = null;
        TextView textView;
        @Override
        public void run() {
            try {
                Log.d(tag,"serviceThread");
                mServiceSocket = new ServerSocket(9001);//統一端口
                mSocket = mServiceSocket.accept();
                InputStream inputStream = mSocket.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                StringBuilder sb = new StringBuilder();
                try {
                    while ((line = br.readLine()) != null) {
                        sb.append(line);
                        sb.append("\n");
                    }
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Message msg = new Message();
                msg.what =100;
                msg.obj = sb;
                mHandler.sendMessage(msg);
mSocket.close();
} catch (IOException e) { e.printStackTrace(); } } }

三、總結:

使用UDP方式通信和TCP發送接受大相徑庭,相同都是進行ip端口設置,只是TCP使用的是流的方式發送,UDP是以包的形式發送。

完整demo可以下載:https://download.csdn.net/download/code_code_88/25312072


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM