版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第5章TCPSocket
5.1套接字5.2TCPSocket5.3多線程操作
5.1套接字
5.1.1端口的概念
在TCP/IP體系結(jié)構(gòu)中,傳輸層為應(yīng)用層提供傳輸服務(wù),可選擇TCP和UDP兩個傳輸協(xié)議充當(dāng)數(shù)據(jù)的承載協(xié)議。應(yīng)用層通過傳輸層進(jìn)行數(shù)據(jù)通信時,TCP和UDP會遇到同時為多個應(yīng)用程序進(jìn)程提供并發(fā)服務(wù)的問題。在TCP/IP協(xié)議中為應(yīng)用層和傳輸層之間提出了端口(port)的概念,用于標(biāo)識網(wǎng)絡(luò)主機(jī)上的唯一通信進(jìn)程。
端口指網(wǎng)絡(luò)體系結(jié)構(gòu)中應(yīng)用層與傳輸層之間的通信協(xié)議接口,也稱為傳輸層服務(wù)訪問接口。端口是一種抽象的軟件結(jié)構(gòu),包括一些數(shù)據(jù)結(jié)構(gòu)和I/O緩沖區(qū)。應(yīng)用進(jìn)程通過系統(tǒng)調(diào)用與某端口建立關(guān)聯(lián)(binding)后,傳輸層傳給該端口的數(shù)據(jù)都被相應(yīng)的應(yīng)用進(jìn)程所接收。TCP與UDP的端口如圖5-1所示。圖5-1TCP與UDP的端口(a)數(shù)據(jù)發(fā)送;(b)數(shù)據(jù)接收端口號使用16位表示,取值范圍為0~65?535,含義是一臺使用TCP/IP體系結(jié)構(gòu)的計算機(jī)上最多在應(yīng)用層上區(qū)別65?336個TCP網(wǎng)絡(luò)進(jìn)程和65?336個UDP網(wǎng)絡(luò)進(jìn)程,實際上不能達(dá)到這樣多的進(jìn)程數(shù)量。所有的端口僅具有本地意義,即端口僅能設(shè)置本地的網(wǎng)絡(luò)通信進(jìn)程,而不能設(shè)置通信對方的應(yīng)用進(jìn)程端口號。表5-1列出了部分基于TCP的常用應(yīng)用進(jìn)程的端口號。習(xí)慣上,端口號可分為三大類:
(1)公認(rèn)端口(WellKnownPorts):從0~1023,它們緊密綁定于一些服務(wù)。通常這些端口的通信明確表明了某種服務(wù)的協(xié)議。例如:80端口實際上總是綁定HTTP通信。
(2)注冊端口(RegisteredPorts):從1024~49?151,它們松散地綁定于一些服務(wù)。也就是說有許多服務(wù)綁定于這些端口,這些端口同樣用于許多其他目的。例如:許多系統(tǒng)處理動態(tài)端口從1024左右開始。
(3)動態(tài)或私有端口(DynamicandorPrivatePorts):從49?152~65?535。理論上,從1024起為服務(wù)分配動態(tài)端口,但也有例外,如Sun的RPC端口從32?768開始。5.1.2套接字的概念
套接字(Socket)原意是“插座”,在計算機(jī)網(wǎng)絡(luò)中指支持TCP/IP的網(wǎng)絡(luò)通信的基本操作單元,可以被看做是兩個進(jìn)程在通信連接中的一個端點,是連接應(yīng)用程序和網(wǎng)絡(luò)驅(qū)動程序的橋梁。Socket在應(yīng)用進(jìn)程中創(chuàng)建,通過綁定與網(wǎng)絡(luò)驅(qū)動建立關(guān)系。此后,應(yīng)用進(jìn)程送給Socket的數(shù)據(jù),由Socket傳遞給網(wǎng)絡(luò)驅(qū)動程序向網(wǎng)絡(luò)上發(fā)送出去。計算機(jī)從網(wǎng)絡(luò)上收到與該Socket綁定IP地址和端口號相關(guān)的數(shù)據(jù)后,由網(wǎng)絡(luò)驅(qū)動進(jìn)程交給Socket,應(yīng)用進(jìn)程便可從該Socket中提取接收到的數(shù)據(jù),即網(wǎng)絡(luò)應(yīng)用進(jìn)程通過Socket實現(xiàn)數(shù)據(jù)的發(fā)送與接收。在同一臺主機(jī)上可能會同時運行多個應(yīng)用進(jìn)程,為了區(qū)分不同應(yīng)用進(jìn)程的網(wǎng)絡(luò)通信和連接,Socket通過三個參數(shù)唯一地標(biāo)識本地主機(jī)上的通信進(jìn)程,實現(xiàn)與網(wǎng)絡(luò)進(jìn)程的綁定關(guān)系,這三個參數(shù)分別是:通信的目的IP地址、使用的傳輸層協(xié)議(TCP或UDP)以及使用的端口號。此時,應(yīng)用層和傳輸層就可以通過Socket,區(qū)分來自不同應(yīng)用程序進(jìn)程或網(wǎng)絡(luò)連接的通信,實現(xiàn)數(shù)據(jù)傳輸?shù)牟l(fā)服務(wù)。
以最常見的WWW訪問為例,例如:在瀏覽器地址中輸入了網(wǎng)頁URL地址:
/index.html該URL就包含了套接字的三個參數(shù),由于采用超文本傳輸協(xié)議(HyperTextTransferProtocol,HTTP)說明使用的是TCP協(xié)議;根據(jù)目標(biāo)網(wǎng)頁的域名“”,可以通過域名服務(wù)器查找到該WWW服務(wù)器的IP地址為;通常在訪問URL時,如端口無特殊指定時,默認(rèn)使用80;index.html說明訪問的文件資源。所以,訪問該網(wǎng)頁時的套接字為{TCP,,80}。5.1.3Netstat的應(yīng)用
由于在TCP/IP體系結(jié)構(gòu)中通過端口唯一標(biāo)識主機(jī)上的應(yīng)用通信進(jìn)程,因而可以通過查看本地端口信息掌握本地主機(jī)的網(wǎng)絡(luò)進(jìn)程運行情況;即:用戶可以知道本地計算機(jī)開放了哪些通信端口,都是什么軟件進(jìn)程開的;可以掌握開放的端口處于什么狀態(tài),是等待連接還是已經(jīng)連接,如果是已經(jīng)連接,需要特別注意看連接是個正常連接還是非正常連接,例如木馬等;可以知道目前本機(jī)是不是正在和其他計算機(jī)交換數(shù)據(jù),是正常的程序訪問到一個正常網(wǎng)站還是訪問到一個陷阱,更重要的是因為端口只能唯一地標(biāo)識通信進(jìn)程,通過查看本地的端口使用情況,可以避免產(chǎn)生端口使用沖突的問題。在Windows操作系統(tǒng)中,提供了工具軟件Netstat.exe。它可以用于顯示與IP,TCP,UDP和ICMP等協(xié)議相關(guān)的統(tǒng)計數(shù)據(jù),通常被用于檢驗本機(jī)各端口的網(wǎng)絡(luò)連接情況。在這里列舉Netstat常用的參數(shù)?-a和?-n,如:
●?Netstat-a 本選項顯示一個有效連接信息列表,包括已建立的TCP連接(ESTABLISHED),也包括TCP監(jiān)聽連接請求(LISTENING)的連接。
●?Netstat-n 顯示所有已建立的有效連接,包括基于TCP和UDP的應(yīng)用進(jìn)程。
通常,將?-a和?-n聯(lián)合執(zhí)行,即Netstat-an,即可列出本地計算機(jī)所有的占用端口情況。所有的端口必然處于下列狀態(tài)之一:●?LISTENING狀態(tài),表示某個端口是個開放的TCP端口,正處于監(jiān)聽狀態(tài),等待遠(yuǎn)程用戶的連接。意味著這是一個使用TCP的協(xié)議服務(wù)器端程序,用于監(jiān)聽客戶機(jī)端的連接。例如:
TCP:21:0LISTENING
從上例可以看出,本地開啟端口21,通常為FTP服務(wù)進(jìn)程。因為IP地址顯示均為,表示該端口還處于監(jiān)聽狀態(tài),未建立連接。
●?ESTABLISHED狀態(tài),表示已建立通信連接,兩臺機(jī)器正在交換數(shù)據(jù),例如:
TCP0:21:3009ESTABLISHED說明主機(jī)0上開啟了FTP服務(wù),與主機(jī)上端口為3009的進(jìn)程建立了連接。當(dāng)主機(jī)53使用瀏覽器訪問某網(wǎng)站時,發(fā)現(xiàn)會有許多源IP地址和目的IP地址相同,并與處于ESTABLISHED狀態(tài)的套接字連接。這由網(wǎng)頁的構(gòu)成形式?jīng)Q定,網(wǎng)頁本身是純文本格式,它通過嵌入的方法鏈接引入各種格式的數(shù)據(jù),所以如果要查看完整的網(wǎng)頁,就需要將嵌入的所有數(shù)據(jù)都下載,所以圖片、flash動畫等都要單獨建立連接,如圖5-2所示。圖5-2當(dāng)訪問某網(wǎng)頁時建立的連接
5.2TCPSocket
由于TCP是面向連接的傳輸控制協(xié)議,因而在Java的包中,為實現(xiàn)TCPSocket提供了兩個基礎(chǔ)類,分別是Socket類和ServerSocket類。
●?Socket類:用于建立一個客戶機(jī)端通信對象,并向服務(wù)器端發(fā)起連接請求,在TCP連接成功后,通信雙方利用自有的Socket實例實現(xiàn)會話;
●?ServerSocket類:建立一個服務(wù)器端對象,專門用于監(jiān)聽客戶機(jī)端的連接請求,其通過accept()方法實現(xiàn)與客戶端的連接,完成TCP連接的三次握手。5.2.1Socket類
Socket類是TCPSocket中重要的類。該類有兩個作用:其一是作為客戶機(jī)端向指定的服務(wù)器發(fā)起連接請求,其二是在服務(wù)器端生成一個與客戶機(jī)端對等的通信實體,實現(xiàn)一對一的通信功能。其類定義如圖5-3所示。圖5-3Socket類的定義其常用構(gòu)造方法:
●?protectedSocket()throwsIOException,建立一個默認(rèn)的TCP客戶端套接字;
●?publicSocket(InetAddressaddr,intport)throwsIOException,向指定InetAddress的目標(biāo)服務(wù)器的端口port發(fā)起連接請求;
●?publicSocket(Stringhost,intport)throwsIOException,向指定名稱的目標(biāo)服務(wù)器的端口port發(fā)起連接請求。
Socket構(gòu)造方法的含義是,向某指定主機(jī)的指定端口發(fā)出連接請求,例如:
Socketsc1=newSocket("",80);//向主機(jī)上的標(biāo)識為80的服務(wù)進(jìn)程發(fā)起連接請求。
Socketsc2=newSocket(“”,80);//向主機(jī)上的標(biāo)識為80的服務(wù)進(jìn)程發(fā)起連接請求。
Socketsc3=newSocket(InetAddress.getByName(“”),80);參數(shù)使用了InetAddress對象,向目標(biāo)的80端口發(fā)起連接請求。
實際上,上面三個連接請求都是實現(xiàn)了向相同的Web服務(wù)器發(fā)起連接請求的功能,只不過是參數(shù)的形式不同而已。
Socket類常用的方法有:
●?publicvoidclose(),關(guān)閉當(dāng)前套接字;
●?intgetPort(),獲得對方Socket端口號;
●?intgetLocalPort(),獲得本地Socket端口號;
●?InetAddressgetInetAddress(),獲得對方InetAddress對象;
●?InetAddressgetLocalAddress(),獲得本地InetAddress對象;
●?InputStreamgetInputStream(), 獲得輸入流對象;
●?OutputStreamgetOutputStream(),獲得輸出流對象。代碼注釋如下:
①第1~2行在網(wǎng)絡(luò)編程時都需要引用java.io和類庫包;
②第5~6行設(shè)定要訪問的主機(jī)名稱為,端口為80;
③第7行聲明客戶端套接字變量cs;
④第9行向預(yù)先設(shè)定好的主機(jī)上的端口發(fā)起連接請求,如果連接成功的話則對客戶端套接字cs進(jìn)行賦值;
⑤第11~12行獲得本次連接套接字信息。
運行結(jié)果如圖5-4所示。圖5-4Socket常用方法演示代碼注釋如下:
①第6行設(shè)定目標(biāo)計算機(jī)名稱;
②第7行設(shè)定端口掃描范圍,應(yīng)在0~65?535之間。
③第8~16行嘗試連接指定主機(jī)的指定端口,并給出提示信息。
由于在測試遠(yuǎn)程主機(jī)端口時,等待應(yīng)答的時間可能會比較長,可以縮小探測端口的范圍。也可以將hostName設(shè)置為localhost或臨近的主機(jī)。運行結(jié)果如圖5-5所示。
當(dāng)利用Socket實現(xiàn)通信時,在實現(xiàn)與服務(wù)器連接后,客戶機(jī)端套接字上分別獲得輸入與輸出流,并且通過相應(yīng)方法從網(wǎng)絡(luò)獲取數(shù)據(jù)和向網(wǎng)絡(luò)發(fā)送數(shù)據(jù)。圖5-5測試主機(jī)的端口開放情況
代碼注釋如下:
①第6~7行分別聲明了輸入和輸出流對象;
②第9行向指定服務(wù)器localhost的80端口發(fā)起連接請求,如果連接成功則給客戶端套接字cs復(fù)制;
③第10~11行在套接字cs上通過getInputStream()和getOutputStream()方法分別獲得輸入和輸出流;
④第19~21行要求客戶端通過鍵盤輸入一個用戶名;
⑤第22~28行實現(xiàn)客戶端與服務(wù)器的通信;
⑥第22行定義了用于接收和發(fā)送數(shù)據(jù)的字符串變量fromServer和fromUser;
⑦第23行通過in.readUTF()從網(wǎng)絡(luò)接收數(shù)據(jù);
⑧第25行判斷收到的字符是否為“bye”,如果是則退出循環(huán)結(jié)束程序;⑨第27行從本地鍵盤輸入信息;
⑩第28行通過os.writeUTF()實現(xiàn)向網(wǎng)絡(luò)發(fā)送數(shù)據(jù);
??第29行通過調(diào)用os.flush()將存儲在本地發(fā)送緩存的數(shù)據(jù)立即向網(wǎng)絡(luò)發(fā)送,保證消息的實時性;
??第31~34行關(guān)閉流和套接字,釋放資源。
該代碼與例5-4配合執(zhí)行,運行結(jié)果如圖5-6所示。圖5-6客戶機(jī)端顯示5.2.2ServerSocket類
ServerSocket類用于在TCP傳輸?shù)姆?wù)器端建立一個監(jiān)聽端口,監(jiān)聽本地服務(wù)器是否接收到客戶機(jī)端的連接請求。當(dāng)接收到客戶機(jī)端連接請求,采用accept()方法確認(rèn)連接,并在本地返回一個Socket對象,利用該Socket對象與客戶機(jī)端Socket實現(xiàn)建立通信連接。其類定義如圖5-7所示。圖5-7ServerSocket類的定義其常用構(gòu)造方法:
●?ServerSocket()throwsIOException,建立一個服務(wù)器端標(biāo)識;
●?ServerSocket(intport)throwsIOException,在指定的端口建立一個服務(wù)器端標(biāo)識。
其端口取值范圍在0~65535之間,當(dāng)取值為0,表示使用本地任何空閑端口建立監(jiān)聽,監(jiān)聽本地某個指定的端口,例如:
ServerSocketss0=newServerSocket(80);//監(jiān)聽TCP80端口是否有連接請求
ServerSocketss1=newServerSocket(0);//監(jiān)聽某一空閑端口是否有連接請求
ServerSocket常用的方法有:
●?publicSocketaccept(),服務(wù)器接收客戶機(jī)端連接請求;
●?intgetLocalPort(),當(dāng)使用ServerSocket(0)構(gòu)造對象時,可獲得自動分配得到的監(jiān)聽端口號;●?publicvoidclose(),停止監(jiān)聽指定端口,關(guān)閉ServerSocket套接字。
由于TCP是面向連接的協(xié)議,提供可靠的通信服務(wù),因而經(jīng)常被用于文件傳輸?shù)扔锌煽啃砸蟮膱鼍爸小.?dāng)使用Java進(jìn)行TCP通信編程時,首先由服務(wù)器端利用ServerSocket開啟服務(wù)端口等待客戶機(jī)端的連接請求。其次,由客戶機(jī)端的Socket發(fā)起連接請求,服務(wù)器端使用accept()方法接收客戶機(jī)端,生成與客戶機(jī)端對應(yīng)的Socket,完成TCP連接建立。接下來服務(wù)器和客戶機(jī)端分別獲得對應(yīng)的輸入/輸出流,即可進(jìn)行通信。最后,通信結(jié)束分別關(guān)閉兩端的數(shù)據(jù)流和套接字,釋放系統(tǒng)資源。
圖5-8所示為TCPSocket通信的流程。圖5-8TCPSocket通信的流程
代碼注釋如下:
①第5~12行啟動監(jiān)聽本地的8080端口;
②第13~19行當(dāng)收到客戶端連接請求,通過accept()實現(xiàn)與客戶端的連接,并生成對應(yīng)的套接字cst;
③第20~21行在套接字cst上獲得輸入和輸出流;
④第24~35行實現(xiàn)與客戶端的通信,直至輸入“bye”為止。
該例程的運行結(jié)果與例5-3配合執(zhí)行,將實現(xiàn)一問一答式通信。運行結(jié)果如圖5-9所示。圖5-9服務(wù)器端顯示
5.3多?線?程?操?作
5.3.1多線程的概念
在上一節(jié)的例子中,實現(xiàn)的是通信最基本的形式“點到點(PointtoPoint,P2P)”通信,其特點是只有2人參與,進(jìn)行一問一答形式的信息交互。如果要實現(xiàn)多于2人參與的互動會話聊天室,在軟件設(shè)計時需要考慮如何接受多個參與者的申請,加入到同一個會話場景。
通常,在基于TCP的網(wǎng)絡(luò)編程中采用按照多線程的解決方案,以不同線程來與不同的用戶建立Socket連接,分別進(jìn)行通信。這樣的解決方案可以很容易在生活中發(fā)現(xiàn),例如火車票銷售系統(tǒng)、銀行存取系統(tǒng)或者是自來水供應(yīng)系統(tǒng)均能為多個客戶同時提供服務(wù)。在計算機(jī)中被執(zhí)行的程序稱為“進(jìn)程(Process)”,它是在計算機(jī)中依次執(zhí)行的指令,獨立占有系統(tǒng)資源,代表主動對象。線程(Thread)指進(jìn)程概念中的程序代碼的執(zhí)行位置。線程是屬于進(jìn)程的,一個進(jìn)程往往存在多個相似的線程。另一種更加形象的比喻是“線程是程序中的一條執(zhí)行路徑”,則多線程表示程序中包含多條執(zhí)行路徑。當(dāng)多個線程同時使用同一資源的時候,將會產(chǎn)生沖突。
【例5-5】
實現(xiàn)一組數(shù)1~30的累加,共啟用3個線程,每個線程都是從該數(shù)據(jù)集合中取10個數(shù)分別累加,最后將各線程的和再累加在一起。
代碼注釋如下:
①第1行因為要實現(xiàn)數(shù)字1~30的累加,所以定義一個共享資源類;
②第2行成員變量count為共享資源,為了避免外部直接引用,使用了private修飾符;
③第3~6行定義count的自增方法為?+1,并且通過synchronized聲明該方法在某個時刻只能被一個線程所調(diào)用,即排他行;
④第8~31行定義實現(xiàn)累加的線程;
⑤第34行定義計數(shù)器對象;⑥第35~40行定義三個累加的線程對象,并將這些對象作為參數(shù)傳遞為Thread類對象;
⑦第41~43行通過start()啟動累加線程;
⑧第44行通過join()將這些子線程加入到主線程中,保證當(dāng)子線程結(jié)束后,主線程才能結(jié)束;
⑨第45行輸出累加結(jié)果。
運行結(jié)果如圖5-10所示。
該例在第9章遠(yuǎn)程方法接口修改為分布式累加。圖5-10多線程累計結(jié)果5.3.2Java的多線程
Java中為用戶自定義線程類提供了兩種方法,分別是:
●?繼承Thread類,例如:
publicclassmyThreadextendsThread{}
●?實現(xiàn)Runnable接口,例如:
publicclassmyThreadimplmentsRunnable{}
這兩種方法都需要調(diào)用run()方法使線程運行。所以,自定義線程時必須覆蓋run()方法。由于Java的單繼承特性,通常建議在自定義線程類時采用Runnable接口。
Thread類提供了七種重載的構(gòu)造方法來實現(xiàn)線程類的實例化,分別是:●?publicThread(),默認(rèn)的構(gòu)造方法;
●?publicThread(Stringname),指定了線程名稱的構(gòu)造方法;
●?publicThread(Runnabletarget),帶有Runnable參數(shù)的構(gòu)造方法;
●?publicThread(Runnabletarget,Stringname),有Runnable參數(shù)和名稱的構(gòu)造方法;
●?publicThread(ThreadGroupgroup,Stringname),帶有線程組名和線程名的構(gòu)造方法;
●?publicThread(ThreadGroupgroup,Runnabletarget),帶有線程組名和Runnable參數(shù)的構(gòu)造方法; ●?publicThread(ThreadGroupgroup,Runnabletaget,Stringname)帶有線程組名和Runnable參數(shù),以及設(shè)定了線程名的構(gòu)造方法;
在利用Thread實現(xiàn)多線程時,需要先自定義線程類,然后聲明線程實例對象,最后調(diào)用start()使線程運行。在利用Runnable實現(xiàn)多線程時,不能直接創(chuàng)建線程類,必須先聲明一個Runnable實例對象,再將該實例傳遞給Thread類,才能調(diào)用start()使線程運行。代碼注釋如下:
①第2~7行與例5~6中的相同;
②第9~10行先聲明一個Runnable對象,再將該對象帶入Thread構(gòu)造方法;
③第11行通過start()啟動線程。
當(dāng)多個線程同時訪問一個資源的時候,就會出現(xiàn)系統(tǒng)運行異常,類似于數(shù)據(jù)庫操作中的臟讀和臟寫,所以引入線程同步的概念來避免它。同步的基本思想是避免多個線程訪問同一資源,可以通過“鎖”的形式實現(xiàn)。Java同步機(jī)制的作用就是力圖避免對“對象”訪問的沖突。為此,提供了一種信號量monitor來控制訪問對象的同步,使用關(guān)鍵字synchronized來修飾方法或者程序段,實現(xiàn)信號量的控制。Synchronized既可以用來鎖完整的成員方法,也可以用來鎖方法中某個程序段。5.3.3多線程與TCPSocket
聊天室(chatroom)是一個典型的多線程通信應(yīng)用程序。如果是基于TCP協(xié)議的通信,則服務(wù)器端必須利用多線程與每個客戶機(jī)端進(jìn)行單獨的連接,并采用線性表或鏈表保存每個客戶機(jī)端的Socket信息,然后由服務(wù)器以逐次轉(zhuǎn)發(fā)消息形式,實現(xiàn)消息的發(fā)布。如果是基于UDP通信,則可以選擇與TCP相類似的方法,也可以使用D類IP多播地址進(jìn)行群發(fā)信息。
在TCP中,首先服務(wù)器開啟指定的端口,用于監(jiān)聽客戶機(jī)端的連接請求??蛻魴C(jī)端發(fā)起連接請求,服務(wù)器端通過accept()接收,生成一個單獨的線程與每一個客戶機(jī)端進(jìn)行獨立的通信,如圖5-11所示。圖5-11基于TCP的多線程通信在程序設(shè)計時,可保持在客戶機(jī)端程序(例5-4)不改變的情況,在原單線程的服務(wù)器(例5-4)上改進(jìn),增加以下部分功能:
(1)設(shè)立主程序線程;
(2)增加while循環(huán),接受客戶機(jī)端的連接請求;
(3)設(shè)立對應(yīng)于客戶機(jī)端的對話線程;
(4)創(chuàng)建線程對象,并啟動該線程。
代碼注釋如下:
①第3行聲明主程序為線程;
②第5~13行在構(gòu)造方法中實現(xiàn)監(jiān)聽本地的指定端口;
③第16~20行采用while循環(huán)的方法無限地接收客戶端的連接請求;
④第25~53行定義客戶端的通信線程類,該類實現(xiàn)了Runnable接口;
⑤第54~58行啟動主程序。
例5-8是一個簡化的多線程服務(wù)器端程序,實際上真實環(huán)境下需要為服務(wù)器主程序、與客戶端連接、接收客戶端消息、給客戶端發(fā)送消息等設(shè)置線程。5.3.4多客戶端信息存儲
在上節(jié)中僅討論了如何使用多線程連接多個客戶機(jī)端。而實際上要滿足一個簡單聊天室的功能,還需要考慮以下重要的內(nèi)容:
●?如何保存客戶機(jī)端的信息,例如,客戶機(jī)端的Socket信息等,當(dāng)服務(wù)器端收到客戶機(jī)端發(fā)送的消息后,如何將消息向聊天室里所有用戶的分發(fā);
●?如何設(shè)計消息的格式,即在聊天室中發(fā)送的消息應(yīng)該包含哪些內(nèi)容,例如,信息的發(fā)送者、接收者目的地,以及內(nèi)容等;圖5-12Java中的線性表和鏈表類通常,為了保存所有連接到服務(wù)器的客戶機(jī)端Socket信息,可以采用Java所提供的線性表Collection或鏈表Map等數(shù)據(jù)結(jié)構(gòu),這些結(jié)構(gòu)保存在java.util類庫中,如圖5-12所示。其中,Java.util.Vector提供了向量(Vector)類以實現(xiàn)動態(tài)數(shù)組的功能,在多線程編程時經(jīng)常被使用。每個Vector實例都有一個容量(Capacity),用于存儲元素的數(shù)組,這個容量可隨著不斷添加新元素而自動增加。
Vector的構(gòu)造方法有:
●?Vector();//構(gòu)造一個空的實例對象
●?Vector(int
initialCapacity);//構(gòu)造一個初始有一個向量的實例對象
●?Vector(int
initialCapacity,int
capacityIncrement);//構(gòu)造一個初始有一個向量,并且每次遞增一個的實例對象例如:
VectoruserList=newVector();
其常用方法有:
Vector.add(element);
//添加一個元素
VectoruserList.remove(socket);
//移除一個指定元素
Vector.size();
//獲取Vector中元素個數(shù)
在例5-8基礎(chǔ)上進(jìn)行修改,第一,需要在myServer類中聲明一個Vector對象,如下:第三,修改客戶通信線類,這時將服務(wù)器端僅作為消息的轉(zhuǎn)發(fā)者,不允許通過鍵盤輸入與客戶機(jī)端對話:第四,為了客戶機(jī)端能及時地收到服務(wù)器轉(zhuǎn)發(fā)過來的消息,需要為客戶機(jī)端的接收和發(fā)送數(shù)據(jù)流分別設(shè)置2個線程。
【例5-9】多線程的客戶機(jī)端代碼。
代碼注釋如下:
①第3行聲明客戶端為線程;
②第4~9行聲明成員變量;
③第14~28行聲明客戶端線程的啟動方法;
④第16行連接指定的服務(wù)器端;
⑤第23行啟動消息的接收線程;
⑥第24行啟動消息的發(fā)送線程;
⑦第29~48行聲明內(nèi)部接收線
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 怎么研究戲曲課程設(shè)計
- 推送機(jī)課程設(shè)計
- 機(jī)場飛行區(qū)課程設(shè)計
- 制造業(yè)企業(yè)數(shù)字化轉(zhuǎn)型實施路徑
- 基站室外建設(shè)課程設(shè)計
- 有機(jī)垃圾破碎的課程設(shè)計
- 挖掘機(jī)課程設(shè)計要求
- 微電子課程設(shè)計作品
- 有關(guān)圖形的早教課程設(shè)計
- 鋁產(chǎn)業(yè)發(fā)展趨勢與市場前景深度分析報告
- DB32∕T 3690-2019 600MPa熱處理、熱軋帶肋鋼筋混凝土結(jié)構(gòu)技術(shù)規(guī)程
- 風(fēng)濕病概述及中國風(fēng)濕病發(fā)展情況ppt
- 2021年食品安全監(jiān)督抽檢培訓(xùn)完整版PPT課件
- 外研版(三起)小學(xué)英語四年級上冊教案(全冊)
- 部編二年級下冊語文詞語表帶拼音
- 檢測大綱-整車檢驗、過程檢驗、零部件入廠檢驗、關(guān)鍵部位檢驗、成品入庫檢驗
- 托輥技術(shù)規(guī)格書
- 踝關(guān)節(jié)扭傷.ppt
- CRH2型動車組一級檢修作業(yè)辦法081222
- 研究生英語議論文范文模板
- 燃?xì)獍踩R測試題(含答案)
評論
0/150
提交評論