基于android的Socket通信

一、Socket通信簡介

Android與服務器的通信方式主要有兩種,一是Http通信,一是Socket通信。兩者的最大差異在于,http連接使用的是“請求—響應方式”,即在請求時建立連接通道,當客戶端向服務器發送請求后,服務器端才能向客戶端返回數據。而Socket通信則是在雙方建立起連接后就可以直接進行數據的傳輸,在連接時可實現信息的主動推送,而不需要每次由客戶端想服務器發送請求。 那么,什么是socket?Socket又稱套接字,在程序內部提供了與外界通信的端口,即端口通信。通過建立socket連接,可為通信雙方的數據傳輸傳提供通道。socket的主要特點有數據丟失率低,使用簡單且易于移植。

1.1什么是Socket Socket

是一種抽象層,應用程序通過它來發送和接收數據,使用Socket可以將應用程序添加到網絡中,與處于同一網絡中的其他應用程序進行通信。簡單來說,Socket提供了程序內部與外界通信的端口并為通信雙方的提供了數據傳輸通道。

1.2Socket的分類

根據不同的的底層協議,Socket的實現是多樣化的。本指南中只介紹TCP/IP協議族的內容,在這個協議族當中主要的Socket類型為流套接字(streamsocket)和數據報套接字(datagramsocket)。流套接字將TCP作為其端對端協議,提供了一個可信賴的字節流服務。數據報套接字使用UDP協議,提供數據打包發送服務。 下面,我們來認識一下這兩種Socket類型的基本實現模型。

二、Socket 基本通信模型

三、Socket基本實現原理

3.1基于TCP協議的Socket

服務器端首先聲明一個ServerSocket對象并且指定端口號,然后調用Serversocket的accept()方法接收客戶端的數據。accept()方法在沒有數據進行接收的處于堵塞狀態。(Socketsocket=serversocket.accept()),一旦接收到數據,通過inputstream讀取接收的數據。

客戶端創建一個Socket對象,指定服務器端的ip地址和端口號(Socketsocket=newSocket("172.168.10.108",8080);),通過inputstream讀取數據,獲取服務器發出的數據(OutputStreamoutputstream=socket.getOutputStream()),最后將要發送的數據寫入到outputstream即可進行TCP協議的socket數據傳輸。

3.2基于UDP協議的數據傳輸

服務器端首先創建一個DatagramSocket對象,并且指點監聽的端口。接下來創建一個空的DatagramSocket對象用于接收數據(bytedata[]=newbyte[1024;]DatagramSocketpacket=newDatagramSocket(data,data.length)),使用DatagramSocket的receive方法接收客戶端發送的數據,receive()與serversocket的accepet()類似,在沒有數據進行接收的處于堵塞狀態。

客戶端也創建個DatagramSocket對象,并且指點監聽的端口。接下來創建一個InetAddress對象,這個對象類似與一個網絡的發送地址(InetAddressserveraddress=InetAddress.getByName("172.168.1.120")).定義要發送的一個字符串,創建一個DatagramPacket對象,并制定要講這個數據報包發送到網絡的那個地址以及端口號,最后使用DatagramSocket的對象的send()發送數據。*(Stringstr="hello";bytedata[]=str.getByte();DatagramPacketpacket=new DatagramPacket(data,data.length,serveraddress,4567);socket.send(packet);)

四、android 實現socket簡單通信

前言:添加權限

<!-- 允許應用程序改變網絡狀態-->

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

<!--允許應用程序改變WIFI連接狀態 -->

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE">

<!--允許應用程序訪問有關的網絡信息-->

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

<!--允許應用程序訪問WIFI網卡的網絡信息-->

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

<!--允許應用程序完全使用網絡-->

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

4.1使用TCP協議通信

android端實現:

protectedvoidconnectServerWithTCPSocket() {

Socket?socket;

try{//?創建一個Socket對象,并指定服務端的IP及端口號

socket?=newSocket("192.168.1.32",1989);

//?創建一個InputStream用戶讀取要發送的文件。

InputStream?inputStream?=newFileInputStream("e://a.txt");

//?獲取Socket的OutputStream對象用于發送數據。

OutputStream?outputStream?=?socket.getOutputStream();

//?創建一個byte類型的buffer字節數組,用于存放讀取的本地文件

bytebuffer[]?=newbyte[4*1024];

inttemp?=0;

//?循環讀取文件

while((temp?=?inputStream.read(buffer))?!=?-1)?{

//?把數據寫入到OuputStream對象中

outputStream.write(buffer,0,?temp);

}

//?發送讀取的數據到服務端

outputStream.flush();

/**?或創建一個報文,使用BufferedWriter寫入,看你的需求?**/

//??????????String?socketData?=?"[2143213;21343fjks;213]";

//??????????BufferedWriter?writer?=?new?BufferedWriter(new?OutputStreamWriter(

//??????????????????socket.getOutputStream()));

//??????????writer.write(socketData.replace("\n",?"?")?+?"\n");

//??????????writer.flush();

/************************************************/

}catch(UnknownHostException?e)?{

e.printStackTrace();

}catch(IOException?e)?{

e.printStackTrace();

}

}

服務器端簡單實現:

publicvoidServerReceviedByTcp() {

//?聲明一個ServerSocket對象

ServerSocket?serverSocket?=null;

try{

//?創建一個ServerSocket對象,并讓這個Socket在1989端口監聽

serverSocket?=newServerSocket(1989);

//?調用ServerSocket的accept()方法,接受客戶端所發送的請求,

//?如果客戶端沒有發送數據,那么該線程就停滯不繼續

Socket?socket?=?serverSocket.accept();

//?從Socket當中得到InputStream對象

InputStream?inputStream?=?socket.getInputStream();

bytebuffer[]?=newbyte[1024*4];

inttemp?=0;

//?從InputStream當中讀取客戶端所發送的數據

while((temp?=?inputStream.read(buffer))?!=?-1)?{

System.out.println(newString(buffer,0,?temp));

}

serverSocket.close();

}catch(IOException?e)?{

e.printStackTrace();

}

}

4.2使用UDP協議通信

客戶端發送數據實現:

protectedvoidconnectServerWithUDPSocket() {

DatagramSocket?socket;

try{

//創建DatagramSocket對象并指定一個端口號,注意,如果客戶端需要接收服務器的返回數據,

//還需要使用這個端口號來receive,所以一定要記住

socket?=newDatagramSocket(1985);

//使用InetAddress(Inet4Address).getByName把IP地址轉換為網絡地址

InetAddress?serverAddress?=?InetAddress.getByName("192.168.1.32");

//Inet4Address?serverAddress?=?(Inet4Address)?Inet4Address.getByName("192.168.1.32");

String?str?="[2143213;21343fjks;213]";//設置要發送的報文

bytedata[]?=?str.getBytes();//把字符串str字符串轉換為字節數組

//創建一個DatagramPacket對象,用于發送數據。

//參數一:要發送的數據??參數二:數據的長度??參數三:服務端的網絡地址??參數四:服務器端端口號

DatagramPacket?packet?=newDatagramPacket(data,?data.length?,serverAddress?,10025);

socket.send(packet);//把數據發送到服務端。

}catch(SocketException?e)?{

e.printStackTrace();

}catch(UnknownHostException?e)?{

e.printStackTrace();

}catch(IOException?e)?{

e.printStackTrace();

}

}

客戶端接收服務器返回的數據:

publicvoidReceiveServerSocketData() {

DatagramSocket?socket;

try{

//實例化的端口號要和發送時的socket一致,否則收不到data

socket?=newDatagramSocket(1985);

bytedata[]?=newbyte[4*1024];

//參數一:要接受的data?參數二:data的長度

DatagramPacket?packet?=newDatagramPacket(data,?data.length);

socket.receive(packet);

//把接收到的data轉換為String字符串

String?result?=newString(packet.getData(),?packet.getOffset(),

packet.getLength());

socket.close();//不使用了記得要關閉

System.out.println("the?number?of?reveived?Socket?is??:"+?flag

+"udpData:"+?result);

}catch(SocketException?e)?{

e.printStackTrace();

}catch(IOException?e)?{

e.printStackTrace();

}

}

服務器接收客戶端實現:

publicvoidServerReceviedByUdp(){

//創建一個DatagramSocket對象,并指定監聽端口。(UDP使用DatagramSocket)

DatagramSocket?socket;

try{

socket?=newDatagramSocket(10025);

//創建一個byte類型的數組,用于存放接收到得數據

bytedata[]?=newbyte[4*1024];

//創建一個DatagramPacket對象,并指定DatagramPacket對象的大小

DatagramPacket?packet?=newDatagramPacket(data,data.length);

//讀取接收到得數據

socket.receive(packet);

//把客戶端發送的數據轉換為字符串。

//使用三個參數的String方法。參數一:數據包?參數二:起始位置?參數三:數據包長

String?result?=newString(packet.getData(),packet.getOffset()?,packet.getLength());

}catch(SocketException?e)?{

e.printStackTrace();

}catch(IOException?e)?{

e.printStackTrace();

}

}


五、總結:

使用UDP方式android端和服務器端接收可以看出,其實android端和服務器端的發送和接收大庭相徑,只要端口號正確了,相互通信就沒有問題,TCP使用的是流的方式發送,UDP是以包的形式發送。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容