Android中基于TCP协议的网络通信之使用Socket进行通信
TCP協(xié)議被稱為一種端到端的協(xié)議。這是因?yàn)樗鼮閮膳_(tái)計(jì)算機(jī)的連接起到了重要作用:當(dāng)一臺(tái)計(jì)算機(jī)需要與另一臺(tái)計(jì)算機(jī)進(jìn)行接連時(shí),TCP協(xié)議會(huì)他們之間建立一個(gè)連接:用于發(fā)送和接收數(shù)據(jù)的虛擬鏈路。
TCP協(xié)議負(fù)責(zé)收集這些信息包,并將其按適當(dāng)?shù)捻樞蚍藕脗魉?#xff0c;在接收端收到后再將其正確地還原。TCP協(xié)議確保了數(shù)據(jù)包在傳送中準(zhǔn)確無(wú)誤。TCP協(xié)議使用重發(fā)機(jī)制:當(dāng)一個(gè)通信實(shí)體發(fā)送一個(gè)消息給另一個(gè)通信實(shí)體后,需要收到另一個(gè)通信實(shí)體的確認(rèn)信息,如果沒(méi)有收到另一個(gè)通信實(shí)體的確認(rèn)信息,則會(huì)重發(fā)剛才發(fā)送的消息。可以通過(guò)下面的圖例來(lái)簡(jiǎn)單了解TCP協(xié)議控制兩個(gè)通信實(shí)體互相通信的過(guò)程:
Java中能接收其他通信實(shí)體連接請(qǐng)求的類是ServerSocket,ServerSocket對(duì)象用來(lái)監(jiān)聽(tīng)來(lái)自客戶端的Socket連接,如果沒(méi)有連接,它將一直處于等待狀態(tài)。
根據(jù)上面的示意圖,可以看出我們至少需要兩個(gè)計(jì)算機(jī)設(shè)備才能進(jìn)行通信。一個(gè)是服務(wù)器端,一個(gè)客戶端。在這里可能有人會(huì)說(shuō):那兩個(gè)人聊QQ、微信的時(shí)候兩個(gè)都是客戶端啊。不錯(cuò),的確兩個(gè)都是客戶端。但是,要知道,這兩個(gè)客戶端都要和騰訊的服務(wù)器連接才能通信。好了,下面我們就來(lái)用代碼來(lái)做一個(gè)綜述。
首先是服務(wù)器端(Java程序,運(yùn)行于PC):
public class SimpleServer {public static void main(String[] args) throws IOException{ServerSocket ss = new ServerSocket(30000);while (true) {Socket s = ss.accept();OutputStream os = s.getOutputStream();os.write(("我是william的忠實(shí)服務(wù)器!" + Calendar.getInstance().getTimeInMillis()).getBytes("utf-8"));os.close();s.close();}} }這里我用的端口號(hào)是30000,一般來(lái)說(shuō)我們推薦使用1024以上的端口號(hào),主要是為了避免與其他的應(yīng)用程序的通用端口發(fā)生沖突。
這里我們用了一個(gè)死循環(huán)來(lái)監(jiān)聽(tīng)來(lái)自客戶端的連接信息。這里我們是把當(dāng)前毫秒時(shí)間傳給了Socket的outputStream。這里一點(diǎn)需要注意,那就是我用了一個(gè).getBytes("utf-8")。這是因?yàn)?#xff0c;我們的服務(wù)器端是運(yùn)行在PC上,一般是Windows主機(jī),當(dāng)直接使用PrintStream輸出字符串時(shí)默認(rèn)使用系統(tǒng)平臺(tái)的字符串(GBK)編碼,但客戶端都是Android程序,運(yùn)行于Linux平臺(tái),因?yàn)榭蛻舳俗x取網(wǎng)絡(luò)數(shù)據(jù)時(shí)默認(rèn)使用UTF-8字符集進(jìn)行解碼,這樣就會(huì)造成亂碼。
----------------------------------------------------------------------------------------------------------------------------------------------------------
下面是客戶端程序(Android程序,運(yùn)行于Android機(jī)):
Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {if (msg.what == 123) {try {Socket socket = new Socket("192.168.1.105", 30000);BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = reader.readLine();TextView showTextView = (TextView) findViewById(R.id.activity_simple_client_textview);showTextView.setText("來(lái)自服務(wù)器的數(shù)據(jù):" + line);reader.close();socket.close();} catch (Exception e) {e.printStackTrace();}}};};這里只提供了在Handler線程中的關(guān)鍵代碼,因?yàn)樵赨I線程的部分非常簡(jiǎn)單,這里不給出代碼,完整代碼后面會(huì)有接連源碼下載。
在客戶端我們使用了IP為192.168.1.105的主機(jī),因?yàn)楣P者的PC就是這個(gè)IP。如果你的電腦你不知道怎么查看IP或是你的IP地址是設(shè)置為自動(dòng)獲取IP地址,那么可以使用下圖的方法(在開始菜單下輸入cmd進(jìn)入命令提示符窗口):
進(jìn)入cmd的方法:
另外如果你需要修改你的服務(wù)器端程序,并且要運(yùn)行修改后的程序,你可能會(huì)遇到這樣的一種情況:
遇到這種情況,不是你的程序修改的時(shí)候有問(wèn)題。而是因?yàn)檫@個(gè)時(shí)候,你的服務(wù)器端程序里寫了一個(gè)死循環(huán),這個(gè)死循環(huán)會(huì)一直在運(yùn)行。我們可以通過(guò)任務(wù)管理器查看到這個(gè)進(jìn)程還在運(yùn)行著,如下:
我們只在kill掉這個(gè)進(jìn)程,然后再運(yùn)行服務(wù)器程序,這樣就可以了。
運(yùn)行程序,如下結(jié)果:
本博客參考資料:《瘋狂Android講義》
這里是我的程序源碼(服務(wù)器端和客戶端):點(diǎn)擊下載源碼
總結(jié)
以上是生活随笔為你收集整理的Android中基于TCP协议的网络通信之使用Socket进行通信的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android Wifi开发之WifiC
- 下一篇: Android在ListView中嵌套一