前言:一篇好文章的誕生,需要你不斷地搜集資料、整理思路,本站小編為你收集了豐富的socket通信主題范文,僅供參考,歡迎閱讀并收藏。
關鍵詞:網(wǎng)絡通信;Tcp/IP;socket
中圖分類號:TP393 文獻標識碼:A 文章編號:1009-3044(2013)35-8116-02
1 C/S中TCP/IP與Socket
1.1 TCP/IP協(xié)議的優(yōu)點
每種網(wǎng)絡協(xié)議都有自己的優(yōu)點,但是只有TCP/IP允許與Internet完全的連接。TCP/IP是在60年代由麻省理工學院開發(fā)的,即便網(wǎng)絡遭到了大部分破壞,TCP/IP仍然能夠維持有效的通信。在所有的OS中都集成了TCP/IP協(xié)議,TCP/IP是實現(xiàn)網(wǎng)際互聯(lián)的基礎,同時TCP/IP協(xié)議也具備了可擴展性和可靠性的需求。在現(xiàn)今的網(wǎng)絡環(huán)境下,能有效地保證點對點信息的傳輸和安全是網(wǎng)絡應用的需要。
1.2 Socket的作用
Socket通常稱作"套接字",應用程序通常通過"套接字"向網(wǎng)絡發(fā)出請求或應答網(wǎng)絡請求,Socket是面向C/S模型而設計的,針對客戶和服務器程序提供不同的socket系統(tǒng)調(diào)用。客戶隨機申請一個socket (相當于在電話系統(tǒng)中一個想打電話的人可以在任何一臺入網(wǎng)電話上撥號呼叫),系統(tǒng)為任何有聯(lián)網(wǎng)需求及信息需求的客戶分配一個socket號;服務器擁有全局socket號 ,客戶端socket號相當于電話系統(tǒng)中的各個公共電話,而服務器端相當于總機電話。
1.3 Socket實現(xiàn)網(wǎng)絡通信的基本原理
TCP/IP系統(tǒng)中的端口號是一個16位的數(shù)字,它的范圍是0~65535。客戶和服務器必須事先約定所使用的端口。在C/S開發(fā)模式中,網(wǎng)絡中的各個節(jié)點都有獨有的IP地址用來表示各節(jié)點的身份,服務器預留端口作為鏈接的接口,而Socket通過在它們之間兩兩建立鏈路的方式,來實現(xiàn)網(wǎng)絡中點對點的通信。
Socket分為客戶端Socket對象及ServerSocket類對象,它們類庫位于包中。ServerSocket用于服務器端,Socket是建立網(wǎng)絡連接時使用的。在連接成功時,應用程序兩端都會產(chǎn)生一個Socket實例,通過這個實例,完成所需的會話。對于一個網(wǎng)絡連接來說,套接字是平等的,并沒有差別,不因為在服務器端或在客戶端而產(chǎn)生不同級別。不管是Socket還是ServerSocket它們的工作都是通過Java語言提供的SocketImpl接口及其方法來完成網(wǎng)絡編程所需的網(wǎng)絡通信功能。 這套API使Java程序員不用考慮復雜的網(wǎng)絡協(xié)議以及底層的數(shù)據(jù)傳輸方式,而直接用面向對象的思想來實現(xiàn)網(wǎng)絡傳輸。
2 建立C/S基于TCP/IP Socket通信模型
2.1 客戶端Socket通信過程
Socket是網(wǎng)絡上運行的兩個程序間雙向通信的一端,它既可以接受請求,也可以發(fā)送請求,利用它可以較為方便地編寫網(wǎng)絡上數(shù)據(jù)的傳遞。在Java中,利用Socket類的方法,就可以實現(xiàn)兩臺計算機之間的通信??蛻舳薙ocket通信整個過程主要有4個階段:(1)請求階段;(2)建立連接階段;(3)通信階段;(4)關閉階段。
2.2 TCP Socket C/S模型及工作流程
TCP/IP本身是一個工業(yè)標準,在C/S模式中,主要通過三次握手,實現(xiàn)通信:
1):主機A發(fā)送位碼為syn=1,隨機產(chǎn)生seq number=1234567的數(shù)據(jù)包到服務器,主機B由SYN=1知道,A要求建立聯(lián)機;
2):主機B收到請求后要確認聯(lián)機信息,向A發(fā)送ack number=(主機A的seq+1),syn=1,ack=1,隨機產(chǎn)生seq=7654321的包;
3):主機A收到后檢查ack number是否正確,即第一次發(fā)送的seq number+1,以及位碼ack是否為1,若正確,主機A會再發(fā)送ack number=(主機B的seq+1),ack=1,主機B收到后確認seq值與ack=1則連接建立成功;
圖1 C/S程序工作流程圖
3 程序實現(xiàn)
3.1 C/S模型下基本程序框架
3.1.1 客戶端Socket的實現(xiàn)
客戶端通過Socket連接服務器,主要過程經(jīng)過4個階段,具體代碼如下:
Socket PersonalConnect=new Socket(“服務器IP”,PORT);
……;//socket、bufferedReader及PrintStream對象作為線程成員
PersonalConnect.close();
3.1.2 服務器端ServerSocket的實現(xiàn)
ServerSocket myTcpServer=new ServerSocket(PORT);//設定服務器端口
while(true){//實現(xiàn)多客戶鏈接
Socket c_s=myTcpServer.accept();
……;//socket、bufferedReader及PrintStream對象作為線程成員
c_s.close();}
對于TCP C/S模式中兩端的Java類中,主要有三個類成員它們分別是Socket對象、BufferedReader對象、PrintStream對象,而服務器端還有個ServerSocket對象。其中Socket及ServerSocket對象完成連接兩端的請求綁定套接的過程,而輸入輸出流在套接中進行通信。如果一端要表達消息發(fā)送結束,則可以關閉其輸出流,但并不關閉套接字對象,這就是“半關閉”的作用。
3.2 通過線程管理C/S中的通信
3.2.1 客戶端ClientThread的實現(xiàn)
ClientThread.java的主要代碼:
public class ClientThread implements Runnable{
……;
public ClientThread(Socket s) throws IOException{
this.personalConnect=s;
……;}
public void run() {……}
}
3.2.2服務器端ServerThread的實現(xiàn)
Tcp_Server.java文件的主要代碼:
public static ArrayList socketList = new ArrayList();
//用來保存客戶端Socket對象
ServerSocket myTcpServer=new ServerSocket(“服務器端口“);
Socket c_s = myTcpServer.accept();
socketList.add(c_s);//響應客戶端Socket請求,并保存Socket對象進入socketList
new Thread(new ServerThread(c_s)).start(); ServerThread.java文件的主要代碼:
public class ServerThread implements Runnable
{……;//socket、bufferedReader及PrintStream對象作為線程屬性
public ServerThread(Socket s) throws IOException {
this.c_s = s; }}
利用線程在一個List結構中實現(xiàn)多個不同的Socket對象的管理即每一個客戶端通過線程實現(xiàn)套接字對象的管理與通信。Accept()方法用于產(chǎn)生”阻塞”,直到接受到一個連接,并且返回一個客戶端的Socket對象實例?!弊枞笔且粋€術語,它使程序運行暫時”停留”在這個地方,直到一個會話產(chǎn)生,然后程序繼續(xù)。
為了更好地實現(xiàn)對于客戶端對象的管理,實現(xiàn)對于其Socket與其消息的管理,我們也可以通過HaspMap對象,來實現(xiàn)單一客戶K與其多條消息V的關系映射。實現(xiàn)“Kclient+Vserver“的形式傳送消息即“用戶名:消息類容”的形式輸入,服務器端以HaspMap解析讀入的消息對象,辨識消息的發(fā)送者與其消息之間的映射關系,實現(xiàn)點對點的消息傳輸。
4 結束語
本文主要介紹的內(nèi)容僅適合于TCP/IP網(wǎng)絡協(xié)議。Java Socket 可以實現(xiàn)TCP協(xié)議在兩臺計算機之間建立可靠連接。連接安全可靠,數(shù)據(jù)不會丟失,Java平臺還提供了更安全的SSLSocket類,SSLSocket通信是對SOCKET通信的拓展。在Socket基礎上添加了一層安全性保護,提供了更高的安全性,包括身份驗證、數(shù)據(jù)加密以及完整性驗證。其中身份驗證用于數(shù)字證書的發(fā)放和應用。數(shù)據(jù)加密可以通過密鑰防止消息傳遞過程中被別人監(jiān)聽而造成的損失。所以Socket編程在網(wǎng)絡通信中得到了廣泛的應用。
參考文獻:
【 關鍵詞 】 Socket通訊;數(shù)據(jù)交互;delphi
USing Socket Communication Technology to Realize Data Security Interaction between
the Systems of Huaian Accumulation Fund Center and Registration Trading Center
Wei Juan 1 Zhao Chun-mei 2
【 Abstract 】 With the development of the electronic administrative affairs, different application systems cause certain difficulties while being developed in the aspects of development environment, system structure and data base, etc. This paper adopts socket communication mode to realize data interaction between the systems of Huaian Accumulation Fund Center and Registration Trading Center. The log processing and image processing specially added also provides a good reference to the interaction of other systems.
【 Keywords 】 socket communication; data interaction; delphi
1 系統(tǒng)間的交互方式
加強淮安市公積金中與淮安市房屋交易登記中心數(shù)據(jù)共享,為社會公眾及自身提供一體化的高效、優(yōu)質(zhì)、廉潔的管理和服務的過程實現(xiàn)住房公積金貸款“一窗辦結”、“一次告知,集中收件”的受理原則,“一次審核、全程通用” 的審查原則?;窗彩泄e金中心與淮安市登記中心系統(tǒng)要實現(xiàn)系統(tǒng)數(shù)據(jù)的共享,但系統(tǒng)架構、數(shù)據(jù)庫不一樣,給數(shù)據(jù)交互帶來一定難度。
常用的數(shù)據(jù)交互技術有Socket和WebSevice。
(1)Socket交互,首先建立Socket數(shù)據(jù)交互包,即兩個系統(tǒng)間建立傳遞數(shù)據(jù)的數(shù)據(jù)包,接受到數(shù)據(jù)包的一端根據(jù)制定的規(guī)則完成交互。該方式優(yōu)點是點對點之間的數(shù)據(jù)交互安全性高。
(2)WebSevice交互以WebSevice 的方式實現(xiàn)服務器間的交互,系統(tǒng)間互為客戶端向服務器端發(fā)送請求實現(xiàn)交互。該方式的優(yōu)點是實時交互效率高;缺點是由于服務器端作為客戶端,有可能出現(xiàn)安全問題。公積金中心采用C/S架構、Oracle數(shù)據(jù)庫,登記中心是C/S架構\SQL Server數(shù)據(jù)庫,雙方業(yè)務系統(tǒng)均在內(nèi)網(wǎng),且對安全性都有很高的要求,不適合直接互聯(lián),雙方均租用電信專線實現(xiàn)網(wǎng)絡互聯(lián)、防火墻等設備保障系統(tǒng)安全。所有采用了Socket方式實現(xiàn)數(shù)據(jù)交互。
Socket是建立在傳輸層協(xié)議上的一種套接字規(guī)范,它定義兩臺計算機間進行通信的規(guī)范,套接字屏蔽了底層通信軟件和具體操作系統(tǒng)的差異,使得任何兩臺安裝了TCP協(xié)議軟件和實現(xiàn)了套接字規(guī)范的計算機之間的通信成為可能。Socket通常用來實現(xiàn)客戶方和服務方的連接。客戶程序可以向Socket寫請求,服務器將處理此請求,然后通過Socket將結果返回給用戶。
2 制定數(shù)據(jù)交換規(guī)范,統(tǒng)一數(shù)據(jù)交換格式
由于公積金系統(tǒng)和登記中心系統(tǒng)的是在不同的數(shù)據(jù)庫開發(fā)的軟件,我們首先要做的事情是,將數(shù)據(jù)的數(shù)據(jù)映射成為統(tǒng)一的數(shù)據(jù)格式,再由統(tǒng)一的數(shù)據(jù)格式映射成為本系統(tǒng)的數(shù)據(jù)格式。
對于數(shù)據(jù)交互格式我們制定了兩種交互方式。
(1)對數(shù)據(jù)統(tǒng)一編碼,對每個交互內(nèi)容確定數(shù)據(jù)項名稱、類型、長度、位置、備注。發(fā)送的信息組合為一個長字符串。接受方通過對字符串的解碼,提取相應的信息,這種模式比較適合交互內(nèi)容較少的信息。
(2)內(nèi)容較多時,可以通過XML進行組織數(shù)據(jù)。
3 基于Delphi的Socket交互的設計
在Delphi中,對Windows Socket進行了有效的封裝,使得可以很方便地實現(xiàn)通信。在Delphi環(huán)境下實現(xiàn)Socket技術通訊,服務器的流程為,首先建立服務器端的的Socket,當檢測到來自客戶端的連接請求時,向客戶端發(fā)送收到連接請求的信息,并建立與客戶端之間的連接。當完成通信后,服務器斷開與客戶端的Socket連接。客戶端的步驟如下。建立客戶端的Socket,確定要連接的服務器的主機名和端口。發(fā)送連接請求到服務器,并等待服務器的回饋信息。連接成功后,與服務器進行數(shù)據(jù)的交互。數(shù)據(jù)處理完畢后,關閉自身的Socket連接,如圖1所示。
3.1 客戶端軟件開發(fā)
客戶端軟件主要實現(xiàn)的功能是向與服務器端建立Socket連接,發(fā)送消息,并接受返回信息,結束后斷開Socket連接。主要通過ClientSocket實現(xiàn)。
一、Java多線程簡介
將多線程機制蘊含在語言中,是Java的一個重要特征。所謂線程,是指程序中的一個執(zhí)行流。在一個進程中,可以有多個線程。這些線程在操作系統(tǒng)的調(diào)度下并發(fā)執(zhí)行,使得每個線程都好像在獨占整個系統(tǒng)資源。而有了多線程這個特性,JAVA可以支持多個程序并發(fā)執(zhí)行。利用Java的多線程編程接口,開發(fā)人員可以方便地寫出支持多線程的應用程序,有效地減少并發(fā)并行程序設計的困難,提供程序執(zhí)行效率。
1.線程的創(chuàng)建
有兩種方法可以創(chuàng)建線程。第一種方法是通過繼承類Thread來創(chuàng)建線程類。子類重載其mn0方法。實現(xiàn)方法如下:
classThieadNameextendsThread{
publicvoidrun(){//run是整個線程類代碼的
入口
…//需要以線程方式運行的代碼
}}
第二種方法是建立一個具有Runnable接口的類。由于Java不支持多繼承性,如果需要類似線程方式運行且繼承其他的類,就必須實現(xiàn)Runnable接口。Runnable接口只有一個方法run()。在類中實現(xiàn)此接口的方法如下:
classThieadNameextendsAppletimplementsRunnable{
publicvoidrun(){
…//需要以線程方式運行的代碼
}}
2.線程的調(diào)用
如果采用第一種方法,創(chuàng)建的線程類的調(diào)用格式如下:ThreadNametest=newThreadName();//test是線程類
ThreadName的一個實例test.start();
start()是線程類的成員函數(shù),用于啟動該線程,該線程將自動調(diào)用run()方法。
如果采用第二種方法,創(chuàng)建的線程類的調(diào)用格式如下:
ThreadNametest=newThreadName();
Threadth=newThiead(test);/組過Thread創(chuàng)建個新的線程
th.start()
3.線程的同步及通信
系統(tǒng)中存在多個線程時,就需要保證線程的同步及相互通信,以期協(xié)調(diào)工作,避免發(fā)生死鎖。Java提供了二個標準的Object類方法wait(),notify()和notifyAll(),以及二個Thread類方法sleep()suspend()和resume(),用于中斷或喚醒線程的執(zhí)行。當線程調(diào)用sleep(),wait()或suspend()方法之后線程就會由可運行狀態(tài)進入阻塞狀態(tài)(blocked),一旦線程睡眠時間到或者是其他線程調(diào)用了notify()或resume()方法后,此線程才會由阻塞狀態(tài)進入可運行狀態(tài)中,然而一個線程是否最終占有CPU,取決于系統(tǒng)的調(diào)度策略。Java1.0在solaris版本中實現(xiàn)的“綠色線程”的調(diào)用策略是讓一個線程持續(xù)處于執(zhí)行狀態(tài)直到有一個更高優(yōu)先級的線程將之打斷,而Windows95和WindowsNT是給每一個處于可執(zhí)行狀態(tài)的線程分配一個時間片,當時間片用完時系統(tǒng)會調(diào)用另一個線程投入運行。
二、網(wǎng)間網(wǎng)的Socket通訊機制
TCP/IP技術的核心部分是傳輸層(TCP和UDP協(xié)議)、網(wǎng)絡層(P協(xié)議)和物理層(面向各種物理硬件技術),能實現(xiàn)這三層協(xié)議的內(nèi)核可稱之為tcp/ip網(wǎng)絡操作系統(tǒng)。tcp/ip協(xié)議技術中的中下層協(xié)議向外提供的只是原始的編程界面,而不是直接的用戶服務,用戶服務要靠核外的應用程序實現(xiàn)。應用程序和tcp/ip核心協(xié)議關系如圖2所示。
即網(wǎng)間網(wǎng)應用程序能夠直接操作的是TCP/P核心協(xié)議提供的編程界面。由于網(wǎng)絡中資源、運算能力和信息的差異,同時又由于網(wǎng)間網(wǎng)通信完全是異步的,因此,在基于TCP/P協(xié)議的網(wǎng)間網(wǎng)中,最主要的進程間相互作用模型是客戶/服務器(client/server)模型??蛻艉头掌鞣謩e是兩個應用程序(進程),客戶向服務器發(fā)出服務請求,服務器作出響應。
網(wǎng)間網(wǎng)進程通信的關鍵是要解決進程的標識和多傳輸協(xié)議的標識問題以及進程間相互作用的模式。在網(wǎng)間網(wǎng)中,全局惟一的標識一個進程需要一個三兀組表示,即用半相關(half-association)來描述一個Socket:
{協(xié)議,本地地址,本地端口號}
而一個完整的網(wǎng)間網(wǎng)進程通信需要由兩個進程組成(兩個端進程),因此一個完整的網(wǎng)間網(wǎng)進程通信必須用一個五元組表示,即用相關(association)來描述一■個完整的Socket:{協(xié)議,本地地址,本地端口號,遠地地址,遠地端口號}其中,一個確定的網(wǎng)間網(wǎng)進程通信只能使用同一個內(nèi)核的高層協(xié)議,不可能通信的一端用TCP而另一端用UDP協(xié)議。故而,兩個協(xié)議相同的半相關才能組成一個合適的相關,兩個三元組組合起來是一個五兀組而非六兀組。每一個Socket有一個本地惟一的Socket號,由操作系統(tǒng)分配。一個本地Socket號,完整地描述了本地進程以及與之通信的遠地進程,因此Socket的語義具有網(wǎng)絡一致性,準確地描述了網(wǎng)絡進程。因此,Socket的關鍵是建立客戶和服務器之間的相關。
Socket編程界面最早由4BSDUNIX系統(tǒng)提出,其主要目的是解決網(wǎng)間網(wǎng)進程通信(IPC)問題。故而,Socket系統(tǒng)調(diào)用與UNIX的文件訪問有許多類似之處,是對UNIX輸入輸出的擴充。Socket是面向客戶/服務器模型設計的,針對客戶和服務器程序提供了不同的Socket系統(tǒng)調(diào)用。服務器擁有全局公認的半相關Socket,這就保證了任何客戶都可以在網(wǎng)絡的任何地方隨機向它發(fā)出聯(lián)接請求和信息請求。Socket的數(shù)據(jù)信息是原始字節(jié)流的形式,通信雙方要在此基礎上進行約定的數(shù)據(jù)格式化和解釋等處理(即相同的協(xié)議),然后才能進行進一步的具體應用操作,這也是實現(xiàn)某種協(xié)議的過程。基于Socket的這種通信機制,在網(wǎng)關(gateway)的作用下可實現(xiàn)TCP/協(xié)議和其他低級協(xié)議,如現(xiàn)場總線協(xié)議CAN(ControllerAreaNetwork)協(xié)議的轉換,進而擴展Internet應用領域,將實時控制功能帶入網(wǎng)絡。Socket通信機制提供了兩種通訊方式:有聯(lián)接和無聯(lián)接方式,分別面向不同的應用需求。使用有聯(lián)接方式時,通信鏈路提供了可靠的,全雙工的字節(jié)流服務。在該方式下,通信雙方必須創(chuàng)建一個聯(lián)接過程并建立一條通訊鏈路,以后的網(wǎng)絡通信操作完全在這一對進程之間進行,通信完畢關閉此聯(lián)接過程。使用無聯(lián)接方式時其系統(tǒng)開銷比有聯(lián)接方式小,但通信鏈路提供了不可靠的數(shù)據(jù)報服務,不能保證信源所傳輸?shù)臄?shù)據(jù)一定能夠到達信宿。在該方式下,通信雙方不必創(chuàng)建一個聯(lián)接過程和建立一條通訊鏈路,網(wǎng)絡通信操作在不同的主機和進程之間轉發(fā)進行。
面向客戶/服務器方式的Socket通信機制模型如圖3所示。
三、Java多線程在網(wǎng)絡編程中的應用
1.Socket客戶端程序設計我們通過一個簡單的應用程序實例來說明其通信程序的工作過程和編程特點。
?X'
importjava.io.;
X
importjava.net.;publicclassJabberServer{publicstaticfinalintPORT=8080;publicstaticvoidmain(String[]args)throwsIOException
{ServerSockets=newServerSocket(PORT)System.out.println(“Started:”s)try
{Socketsocket=s.accept();try
{System.out.println(“Connectionaccepted:”+socket)
DatalnputStreamsi=newDataInputStream(socket.getInputStream());
PrintSteamso=newPrintStream(socket.getOutputStream());while(true){Stringstr=in.readLine();if(str.equal(“END”))break;
System.out.println(“Echoing:”+str);System.out.println(str);
}finally{
System.out.println(“closing"?”);}}}
此應用程序的功能是從輸入流中獲取從服務器方發(fā)來的數(shù)據(jù),并顯示在屏幕上。Socket類是覆蓋在一個與平臺有關的實現(xiàn)之上的,只是它把具體的系統(tǒng)細節(jié)從java程序中屏蔽了。因而在程序開始部分引入了java.net包中的所有的Socket類?;诖耍琂ava程序即可實現(xiàn)與平臺的無關性。網(wǎng)絡通信的目的主要是對網(wǎng)絡資源的訪問和操作。在建立了新的Socket對象實體s后,利用outputStream(),getTnputStream()方法建立輸出、輸入流。這樣,訪問的網(wǎng)絡資源的過程就變成了處理流對象的過程,即以數(shù)據(jù)流中的方法讀寫應用程序端。數(shù)據(jù)流(Stream)可以理解成數(shù)據(jù)的通信途徑,在建立好應用程序和資源方的通信通道后,遠方的數(shù)據(jù)就可以自動傳輸過來。在程序的結尾用close()方法關閉輸入、輸出流和Socket,這樣將釋放所占用的系統(tǒng)資源。
Java語言的Socket通信機制和UNIX系統(tǒng)的輸入輸出操作(open-read-write-close)相類似。其客戶端基本操作程序的編寫概括起來包括以下四步:①打開Socket,即創(chuàng)建一個Socket對象實體:②創(chuàng)建與此Socket聯(lián)接的輸入輸出流;③根據(jù)服務器的協(xié)議向此Socket寫數(shù)據(jù)或從Socket讀數(shù)據(jù):④關閉輸入、輸出流和Socket。
2.Socket服務器端程序設計基于Java語言的Socket服務器端基本操作過程和客戶端過程相對應,其程序的編寫也包括以下五步:①打開SeneSocket,即創(chuàng)建一個ServerSocket對象實體在指定端口為客戶端請求的Socket服務;②使用ServerSocket類的accept()方法接收來自客戶端的聯(lián)接請求;③使用新建的Socket對象創(chuàng)建輸入、輸出流對象;④通過對流對象的操作完成客戶端的處理請求,并將結果返回給客戶端;⑤當客戶端和服務器工作結束時,關閉輸入、輸出流,用ServerSocket類的close()方法關閉Sacket。
服務器通常分為并發(fā)服務器和重復服務器,并發(fā)服務器只接收客戶請求,不處理請求,客戶請求由它的fork之進程處理和響應;而重復服務器接收、處理并響應客戶請求,即工作時只能同時和一個客戶程序聯(lián)接。下面給出使用Java的多線程實現(xiàn)并發(fā)服務器通信程序。具體地實現(xiàn)并發(fā)服務器的思路是:在服務器的程序中首先創(chuàng)建單個ServerSocke^并調(diào)用accept()來等候一個新連接,然后用accept()返回的Socket新建一個線程,它只為連接的特定的客戶提供服務。接著再調(diào)用accept(),等候下一個親新的連接請求。
(1)服務器端主線程程序的實現(xiàn)
?..+x.importjava.io.;
x
importjava.net.;publicclassMultiJabberServer{publicstaticfinalintPORT=8080;publicstaticvoidmain(String[]args)throwsIOException
{ServeiSockets=newServerSocket(PORT);System.out.println(“ServerStarted”)try
{while(true)
{Socketsocket=s.accept()by
{newMyserverHandler(socket)
}catch(IOExceptione){socket.close()
}
}
}finally{
si.close()so.close();s.close();
}
}
(2)服務器端子線程程序的實現(xiàn)publicclassMyserverHandlerextendsThread{privateSocketsocket;
privateBufferReaderin;privatePrintWriterout;
publicMyserverHandler(Sockets)throwsIOException
{socket=s;
in=newBufferReader(newInputStreamReader(socket.getlnputStream()));
out=newPrintWriter(newBufferedWriter(newOutStreamWriter(socket.getOutputStream()))true);
start();
publicvoidiun(){
by{
while(true){
Stringstc=in.readLine()if(str.equals(“END”)break;
System.out.println(“Echoing:+str);out.pnintln(str)
}
System.out.Println(“closing"?,,);
}finally{
try{
socket.close();
}catch(IOException。){}
}
1
四、結語
關鍵詞:Linux;嵌入式;網(wǎng)絡編程
中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2009)15-3953-02
Applications of Network Programming in Embedded Linux Systems
JIANG Ai-zhen
(Channel 561 in SARFT,NanChang 330046,China)
Abstract: Linux supports a wide range of types of socket addresses and the abstract cluster as a single socket interface, the introduction of the abstract is for the convenience of Internet application programming, as well as web applications to provide data communications between the convenience. In this paper, starting from the basic concepts of socket, introduced the basic model of network programming and the Linux kernel support for the socket.
Key words: Linux; Embedded; Network programming
1 socket概述
在Linux中的網(wǎng)絡編程是通過socket套接字接口來進行的,這一抽象的引入是為了方便聯(lián)網(wǎng)應用程序的編程,在UNIX的BSD版本第一次使用了這種接口,因此他也叫做BSD套接字。應用程序可以使用這種統(tǒng)一接口收發(fā)網(wǎng)絡上的數(shù)據(jù),網(wǎng)絡的socket數(shù)據(jù)傳輸是一種特殊的I/O口,socket也是一種文件描述符。套接字的設計符合Linux的習慣,在理想情況下,應將所有可讀寫訪問的對象映射成文件,這樣就可以用普通的文件讀寫操作來處理這些對象了,使通信中的收發(fā)可以很容易映射成讀寫操作。在傳輸協(xié)議的上下文中,由這類讀寫操作的對象就是通信關系的兩端,他們表示成了套接字。
BSD套接字是一個通用接口,它支持不同的網(wǎng)絡結構,同時也是一個內(nèi)部進程間通信機制。當一個主機上同時有多個應用程序在運行,他們使用tcp和udp協(xié)議進行通信,則傳輸層協(xié)議收到數(shù)據(jù)后將根據(jù)端口和套接口區(qū)分數(shù)據(jù)是傳給哪個應用程序。端口是標識傳輸層與應用程序的數(shù)據(jù)接口,每個端口有一個16位的標識符。套接口是IP地址與端口號的組合,用來標識全網(wǎng)范圍內(nèi)的唯一一個端口,在tep和udP協(xié)議中用來標識一個連接,網(wǎng)絡應用程序之間通過套接口來實現(xiàn)通信。套接字是套接口描述字的簡稱,是整型數(shù)字,它與文件描述符共用一段數(shù)值空間O_65535。應用程序中使用套接字來調(diào)用套接口,套接字可認為是指向套接口的指針,就像文件描述符是指向文件的指針一樣。一個套接字描述了一個鏈接的一個端口,一個socket端點可以用socket地址來描述,socket地址結構由正地址,端口和使用協(xié)議組成(TCPorUDP),因此兩個互聯(lián)的進程都要有一個描述他們之間連結的套接字。我們也可以把套接字看作為是一種特殊的管道,只是這種管道對于包含的數(shù)據(jù)量沒有限制。套接字存在于特定的通信域(即地址族)中,只有隸屬于同一地址族的套接字才能建立對話。Linux支持的協(xié)議族有AF_INET(IPv4協(xié)議)、AF_INET6(IPv6協(xié)議)和AF_UNIX(Unix域協(xié)議)。
Linux支持多種套接字類型,每種套接字類型對應于創(chuàng)建套接字的應用程序所希望的通信服務類型。同一協(xié)議簇可能提供多種服務類型,比如TCP/IP協(xié)議族提供的虛電路和數(shù)據(jù)報就是兩種不同的通信服務類型。TCP/IP中常用的socket類型共有三種,一種是流式socket(SOCK_STREAM),另一種是數(shù)據(jù)報式socket(SOCK_DGRAM),還有一種是原始socket(SOCK_RAW)。流式socket是一種面向連結的socket,對應于面向連接的TCP服務應用。數(shù)據(jù)報式socket是一種無連接的socket,對應于無連接的UDP服務。原始套接字接口容許對較低層協(xié)議如IP、ICMP直接訪問,常用于檢驗新的協(xié)議實現(xiàn)或訪問現(xiàn)有服務中的新設備。
2 網(wǎng)絡編程基本模式
2.1 客戶機/服務器模式
網(wǎng)絡編程的基本模式是Client/Serve:模式,該模式的建立基于以下兩點:
1) 非對等作用;2)通信完全是異步的客戶機/服務器模式在操作過程中采取的是主動請示方式,首先服務器方要先啟動,并根據(jù)請示提供相應服務。Server端首先調(diào)用socket創(chuàng)建一個一定類型socket,然后通過bind函數(shù)將這個socket綁定到一個client知道的端口上,接著server調(diào)用Listen函數(shù)設置傾聽隊列的長度,為了接收來自client端的請求做準備,然后server調(diào)用accept,開始在所綁定的端口傾聽來自client端的連接請求。如果socket被設置成阻塞方式, accept調(diào)用將被阻塞,進程被掛起,直到server收到來自client的請求后,accept才返回。Client端通過socket調(diào)用創(chuàng)建一個一定類型的socket(應當和server的socket類型相同)。然后調(diào)用connect函數(shù)向server所在的主機發(fā)出連接請求,連接時,需要指定server所在主機的IP地址和server傾聽的端口號,連接的報文包含了client端的初始的序號SYN a和MSS=1460信息(最大數(shù)據(jù)段的大小)。正在傾聽來自client的連接請求的server收到client的連接請求后,server從accept調(diào)用中返回(通常socket是阻塞方式工作的)。server將會向client端發(fā)送server端的初始序號SYN b和對client端的SYN a的確認ACK=a+l,還有本端的最大數(shù)據(jù)MSS當client端接收到server端的回應時,將發(fā)出對server請求的ACK=b+1。然后client從connect中返回,返回值是一個打開的socket的描述符,這個描述符和文件的描述符類似,程序可以像使用文件的描述符一樣使用它。稍后,在server端收到client端對其請求的回應時,server將從accept調(diào)用返回,返回值也是一個socket的描述符。
2.2 面向連接協(xié)議的字節(jié)流套接字編程
字節(jié)流socket采用的是傳輸控制協(xié)議TCP。TCP提供面向連接的流傳輸,面向連接對可靠性的保證首先是它在進行數(shù)據(jù)傳輸前,必須在信源端和信宿端建立連接。在面向鏈接傳輸?shù)拿恳粋€報文都需要接收端確認,未確認的報文被認為是出錯報文。字節(jié)流套接字的服務器進程和客戶進程在通信前必須先建立連接,建立連接和通信的步驟如下:
1) 服務進程首先調(diào)用Socket()創(chuàng)建一個字節(jié)流套接字,并調(diào)用bind()將服務器地址捆扎在該套接字上,接著調(diào)用listen()監(jiān)聽連接請求,隨后調(diào)用accept()做好與客戶進程建立連接的準備,無連接請求時,服務進程被阻塞;
2) 客戶進程調(diào)用Socket()創(chuàng)建字節(jié)流套接字,然后調(diào)用connect()向服務進程發(fā)出連接請求;
3) 當連接請求到來后,服務進程被喚醒,生成一個新的字節(jié)流套接字,并用新套接字同客戶進程的套接字建立連接,而服務進程最早生成的套接字則繼續(xù)用于監(jiān)聽網(wǎng)絡上的服務請求;
4) 服務進程和客戶進程通過調(diào)用read()和write()交換數(shù)據(jù);
5) 服務進程和客戶進程通過調(diào)用close()撤消套接字并中斷連接;當選擇SOCK STREAM(字節(jié)流)類型的時,sock()系統(tǒng)調(diào)用中的參數(shù)protocol(協(xié)議)總會選中TCP,而UDP則一直用作SOCK DGRAM類型的傳輸協(xié)議。
2.3 非連接協(xié)議的數(shù)據(jù)報套接字編程
數(shù)據(jù)報式socket采用的是用戶數(shù)據(jù)報協(xié)議UDP,它是建立在IP協(xié)議之上的,提供無連接數(shù)據(jù)報傳輸,主要應用在高可靠性、低延遲的局域網(wǎng)上,它的優(yōu)點是高效率低開銷,不用建立連接和撤銷連接,缺點是不可靠,報文丟失后需重發(fā)。數(shù)據(jù)套接字的服務進程客戶進程通信前不必建立連接,UDP則一直用作SOCKpGRAM類型的傳輸協(xié)議,通信的步驟如下:
1) 服務進程首先調(diào)用Socket()創(chuàng)建一個數(shù)據(jù)套接字,并調(diào)用bind將服務器地址捆扎在該套接字上,然后調(diào)用recvfrom()等待客戶進程發(fā)來的請求;
2) 客戶進程在調(diào)用SocketQ創(chuàng)建一個數(shù)據(jù)報套接字后,調(diào)用bindU將客戶機地址捆扎在此套接字上,接著調(diào)用sendto()向服務進程發(fā)送請求,然后調(diào)用recvfrom()等待服務進程返回該請求的處理結果;
3) 服務進程在執(zhí)行客戶進程所請求的任務后,調(diào)用sendto()將處理結果返回給客戶進程;
4) 服務進程和客戶進程通過調(diào)用close()撤消套接字;
3 Linux內(nèi)核對socket的支持
確切地說,Linux內(nèi)核只提供了一個與套接字有關的系統(tǒng)調(diào)用,應用程序的所有套接字調(diào)用都會映射到這個系統(tǒng)調(diào)用上。在Linux內(nèi)核中的net/socket.c中定義這個函數(shù)sys_socketcall(int call,unsigned long *args)。 include/asm/unistd.h中會指派一個數(shù)字,該數(shù)字會和arch/i386/kernel/entry.s中的系統(tǒng)調(diào)用一起添加到表格中。通過調(diào)用中。all參數(shù)可以說明所指向的那個套接字函數(shù),在include/linux/net.h中定義了可接受的參數(shù)SYS_SOCKET, SYS_IND,SYS_CONNECT, SYS_LISTEN等,在用戶空間的函數(shù)庫中,帶有特定參數(shù)的sys_socketcall調(diào)用會映射成某個獨立函數(shù),在內(nèi)核中若要選中希望調(diào)用的那個函數(shù),需要在sys_socketcall函數(shù)中用到一條:witch命令如下所示,而在此之前首先要使用copy_from_user()命令將sys_ socketcall()的函數(shù)復制到一個向量中,即ensign long a中。
if copy_from user(a,args,nargs(call))
return _EFAULT;
a0=a[0];
al=a[1];
switch(call)
{
case
SYS_SOCKET:
err=sys_socket(a0,al,a[2]);
break;
SYS_BIND:
err=sys_bind(a0,al,a[2]);
break;
SYS_CONNECT:
err=sys_connect(a0,al,a[2]);
break;
為了支持BSD套接字,一個重要的數(shù)據(jù)結構就是struct socket,它的定義位于
include/linux/net.h中,其定義如下:
struct socket
{
socket statestate;
unsigned long flags;
struct proto_ops *ops;
structmode *inode;
structfasync struct *fasync list;
structfile*file;
structsock*sk;
wait queue head t wait;
shorttype;
unsigned char passcred;};
與早期的內(nèi)核相比,socket結構己經(jīng)稍有簡化。state中存儲的是套接字狀態(tài)可以取值如下(include/linux/net.h):SS_FREE(不忙)、SSes UNCONNECTED(未連通)、SS_ONNECTING(目前正在連接)、SS_ONNECTED(已連通)、SS_ISCONNECTING(目前正在斷開連接)。flags用以同步訪問,ops指針指向了連通協(xié)議(如tcp或udp)在初始化之后的協(xié)議運作。就像Linux中的每個文件都有一個mode一樣,每個BSD套接字也分派了一個mode o file中存儲了一個指向該文件結構的指針,這個結構連接了套接字,因此它可以用與指向套接字。如果有進程等待著這個套接字上的事件,也可以通過fasync_list找出該進程。通過sk指針可以使用一個匹配的sock結構。不過,這個sock結構是由BSD套接字之下、特定于協(xié)議的套接字初始化的,并且連通到這個指針。字段負責根據(jù)用戶空間中的同名套接字調(diào)用存儲第二個參數(shù),在Linux內(nèi)核include/asm/socket.h中定義了可接受的參數(shù)。
從上面分析可以看出任何時候通過一個socket來讀寫數(shù)據(jù)時,都是在使用一個系統(tǒng)調(diào)用(system_call)這個調(diào)用(例如read或write)跨越了用戶空間應用程序與內(nèi)核的邊界。另外,在進入內(nèi)核之前,您的調(diào)用會通過C庫來進入內(nèi)核中的一個通用函數(shù)system_call()。從system_call()中,這個調(diào)用會進入文件系統(tǒng)層,內(nèi)核會在這兒確定正在處理的是哪種類型的設備。最后,調(diào)用會進入socket層,數(shù)據(jù)就是在這里進行讀取或進行排隊從而通過socket進行傳輸?shù)摹?/p>
4 總結
每種網(wǎng)絡協(xié)議都提供網(wǎng)絡應用開發(fā)接口,TCP/IP協(xié)議的應用開發(fā)接口的事實標準是socket套接口,開發(fā)socket的目的是隱藏網(wǎng)絡底層的復雜結構和協(xié)議,使編程人員能夠簡單抽象的對網(wǎng)絡進行操作。socket面向客戶機/服務器模型,針對客戶機/服務器程序提供不同的socket的系統(tǒng)調(diào)用函數(shù),客戶端隨機申請一個socket,操作系統(tǒng)為之分配一個隨機socket號;服務器端擁有全局公認的socket號,任何客戶都可以向他發(fā)送連接請求和信息請求。進程通信以前,雙方必須各自創(chuàng)建一個端口,否則是沒有辦法在通信前建立聯(lián)系的,而socket提供了這種進程間通信的端口。從網(wǎng)絡編程的套接字的分析來看,選擇TCP套接字和選擇UDP套接字編程,在傳輸數(shù)據(jù)時有著速度、效率和穩(wěn)定性的差別。TCP編程擁有了可靠的數(shù)據(jù)連接,UDP不具有。但是在速度方面,UDP編程確優(yōu)于TCP編程,特別是對于傳輸短消息?;谶@兩種通信方式優(yōu)缺點的考慮,在后續(xù)編寫IDU控制應用軟件時,將UDP套接字用于硬件終端對外廣播本地IP地址,使局域網(wǎng)內(nèi)客戶端軟件識別某臺終端設備,獲取其MAC地址等硬件信息。將TCP套接字用于在客戶端傳輸用戶數(shù)據(jù),對硬件終端上的硬件設備進行初始化設置。
參考文獻:
[1] Warren W Gay. Linux Socket Programming by Example. Que(R), April 2000.
[2] Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman. Linux Device Drivers 3rd Edition. Reilly Media Inc,2005.
[3] 孫瓊,嵌入式Linux應用程序開發(fā)詳解[M],北京:人民郵電出版社,2006.
關鍵詞:Windows Socket;TCP/IP;阻塞;非阻塞;異步選擇機制
中圖分類號:TP393文獻標識碼:A文章編號:1009-3044(2008)09-11598-02
The Implementation of LAN Communication Based on Asynchronous Selection Mechanism
YANG Xiao-yan, BAI Ya-xiu
(Ankang University, Ankang 725000, China)
Abstract: Internet is increasingly universal in our country, customer's needs to network application also increase continuously. For the network condition's fast changing, to network application procedure development personnel, it is very important to develop the highly effective windows network application procedure. The article introduces Windows Socket, Asynchronous Selection Mechanism briefly and the implementation of LAN communication based on the mechanism according to the basic principle of the network correspondence with VC in dail.The method has characteristics of real time and high efficiency, and may be widely applied in C/S structure softwares.
Key words: Windows Socket; TCP/IP; Blocking; Non-blocking; Asynchronous Selection Mechanism
1 引言
Internet在我國日益普及,用戶對網(wǎng)絡應用的需求也不斷增長,提高網(wǎng)絡程序的效率就顯得相當重要。網(wǎng)絡由一系列協(xié)議組成,TCP/IP協(xié)議是當今異種機互聯(lián)的工業(yè)標準,它支持不同廠家、不同操作系統(tǒng)的計算機之間的通信。TCP/IP協(xié)議族的分層結構中的傳輸層為相互通信的主機提供了端到端的通信能力。其中,TCP協(xié)議向應用層提供可靠的數(shù)據(jù)連接,它保證進程間數(shù)據(jù)傳輸?shù)恼_、有序和不重復。UDP協(xié)議僅僅為應用層提供數(shù)據(jù)報的分組發(fā)送服務,數(shù)據(jù)傳輸?shù)目煽啃灾荒芡ㄟ^應用層來保證。TCP和UDP的主要差別在于可靠性,TCP高度可用,需要大量功能開銷,而UDP是簡單、高效。由于是在局域網(wǎng)中實現(xiàn)通信,為了達到簡單、實時、高效的目的,在介紹Windwins Socket,異步選擇機制,網(wǎng)絡通信原理等相關知識的基礎上,根據(jù)基于數(shù)據(jù)報套接字(UDP協(xié)議)的編程步驟,詳細探討了在VC中基于異步選擇機制的局域網(wǎng)通信的實現(xiàn)。
2 Windows Socket及異步選擇機制
2.1 Windows Socket
套接字(Socket)是建立在傳輸層協(xié)議(主要是TCP和UDP)上的一種套接字規(guī)范,最初是由美國加州Berkley大學提出,它定義了兩臺計算機間進行通信的規(guī)范,套接字屏蔽了底層通信軟件和具體操作系統(tǒng)的差異,使得任何兩臺安裝了TCP協(xié)議軟件和實現(xiàn)了套接字規(guī)范的計算機之間的通信成為可能。Windows Scoket是UNIX操作系統(tǒng)下的Bakeley Socket應用程序開發(fā)接口在Windows環(huán)境下的實現(xiàn)。Windows Socket規(guī)范主要有WinSock1.1和WinSock2兩個版本,它們保持了和Bekeley Socket函數(shù)的兼容性,并做出了重要擴充。這些擴充主要是增加了一些異步請求函數(shù)和對網(wǎng)絡事件的異步選擇機制,使之更適合Windows平臺消息驅動的特性。
2.2 異步選擇機制
Windows Socket在兩種模式下執(zhí)行I/O操作,阻塞和非阻塞。在阻塞模式下,在I/O操作完成前,執(zhí)行操作的Winsock函數(shù)會一直等待下去,不會立即返回程序(將控制權交還給程序)。Windows Sockets為了支持Windows消息驅動機制,使應用程序開發(fā)者能夠方便的處理網(wǎng)絡通信,它對網(wǎng)絡事件采用了基于消息的異步存取策略。Windows Sockets的異步選擇函數(shù)WSAAsyncSelect()提供了消息機制的網(wǎng)絡事件選擇,當使用它登記的網(wǎng)絡事件發(fā)生時,Windows應用程序相應的窗口函數(shù)將收到一個消息,消息中指示了發(fā)生的網(wǎng)絡事件,以及與事件相關的一些信息。這個函數(shù)自動設置套接字為非阻塞模式。
Int WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg)
S,標識了請求事件通知的套接字描述符。
hWnd,標識當一個網(wǎng)絡事件發(fā)生時,接收消息的窗口的句柄
wMsg,網(wǎng)絡事件發(fā)生時,窗口接收到的消息(這里指的是一個自定義的消息。)
lEvent,指定應用感興趣的網(wǎng)絡事件。
3 網(wǎng)絡通信的基本原理
網(wǎng)絡通信實質(zhì)上是網(wǎng)絡中的不同主機進程之間的相互通信(可以把同機進程通信看作其中的特例)問題。與單純的同機通信相比,網(wǎng)絡通信需要解決以下三個問題。第一,標識網(wǎng)絡中的進程。在同一主機上,不同進程可以用進程標識符來標識,而在網(wǎng)絡通信中則是利用端口號來標識。端口是TCP和UDP與應用程序打交道的訪問點,是TCP/IP協(xié)議軟件的一部份。TCP/IP協(xié)議規(guī)定了一些標準保留端口,主要提供給服務器進程使用,用戶進程可以申請使用非保留端口,其端口的標識符在本機種具有唯一性。因此可以利用端口號作為網(wǎng)絡中進程本身的標識。第二,多重協(xié)議的識別。網(wǎng)絡中的兩個進程必須使用協(xié)議來相互通信,而網(wǎng)絡協(xié)議有多種,這就要求進程能夠在眾多的協(xié)議中作出選擇。原因在于不同的協(xié)議地址格式不同、工作方式不同(比如面向連接與無連接),協(xié)議端口分配是相互獨立的。綜合以上兩點,在網(wǎng)絡中全局地址標識一個本地進程需要一個三元組:協(xié)議,本地地址,本地端口號。而一個完整的網(wǎng)絡通信實例是由通信兩端的進程組成,因此需要一個五元組來標識:協(xié)議,本地地址,本地端口號,異地地址,異地端口號。這里的本地地址、異地地址是用來標識計算機的,一般是指計算機的IP地址。第三,進程之間相互作用模式,即應用程序相互作用的模式。在網(wǎng)絡中兩個應用程序間主要的作用模式是客戶機/服務器模式,在這種模式中客戶應用程序向服務器程序請求服務,這種方式隱含了在建立客戶機/服務器間通信時的非對稱性。表1顯示了基于數(shù)據(jù)報套接字的客戶機/服務器編程模型。
4 基于異步選擇機制的局域網(wǎng)通信的實現(xiàn)
4.1 實現(xiàn)思想
根據(jù)數(shù)據(jù)報套接字的客戶機/服務器編程模型,采用Windows Scoket的異步選擇機制,將服務器端和客戶端在同一個程序中實現(xiàn)。需要通信的計算機只要運行同樣的程序,通過輸入對方的IP地址,或主機名就可以實現(xiàn)相互通信。
4.2 在VC中的具體實現(xiàn)
4.2.1 創(chuàng)建基于對話框的MFC EXE工程
在應用程序類的初始化函數(shù):InitInstance()種調(diào)用如下語句加載套接字庫進行版本協(xié)商。(采用Winsock2版本)
WSAStartup(wVersionRequested,&wsaData);
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{WSACleanup();return FALSE;}
在預編譯頭文件中包含頭文件winsock2.h,并鏈接庫文件ws2_32.lib.
4.2.2 服務器端的實現(xiàn)
m_socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0);//創(chuàng)建數(shù)據(jù)報套接字
SOCKADDR_IN addrSock;//地址結構體的定義
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(6000);//端口號為6000
//將套接字綁定到一個本地地址和端口上
bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
//采用異步選擇機制注冊網(wǎng)絡讀取事件
WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ);
#define UM_SOCK WM_USER+1 //自定義消息UM_SOCK
afx_msg void OnSock(WPARAM,LPARAM);//消息響應函數(shù)原型聲明
ON_MESSAGE(UM_SOCK,OnSock)//消息映射
//接收數(shù)據(jù)(消息響應函數(shù)的實現(xiàn))
OnSock(WPARAM wParam,LPARAM lParam)
{ switch(LOWORD(lParam))//判斷是否是網(wǎng)絡讀取事件發(fā)生了。
{case FD_READ:
if(SOCKET_ERROR==WSARecvFrom(m_socket,&wsabuf,1,&dwRead, &dwFlag,(SOCKADDR*)&addrFrom,&len,NULL,NULL))
{MessageBox("接收數(shù)據(jù)失??!"); return;}
str.Format("%s說:%s",inet_ntoa(addrFrom.sin_addr),wsabuf.buf);
str+="\r\n";
GetDlgItemText(IDC_EDIT_RECV,strTemp);
str+=strTemp;
SetDlgItemText(IDC_EDIT_RECV,str);
break;
}
}
4.2.3 客戶端(實現(xiàn)數(shù)據(jù)的發(fā)送)
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP); //獲取服務器端的IP地址
SOCKADDR_IN addrTo;// 接收方地址結構體定義
addrTo.sin_addr.S_un.S_addr=htonl(dwIP);
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(6000);
//將數(shù)據(jù)發(fā)給服務器
if(SOCKET_ERROR==WSASendTo(m_socket,&wsabuf,1,&dwSend,0,
(SOCKADDR*)&addrTo,sizeof(SOCKADDR),NULL,NULL))
{MessageBox("發(fā)送數(shù)據(jù)失敗!");return; }
4.3.4 在應用類及對話框類的析構函數(shù)中分別終止套接字庫,關閉套接字
WSACleanup();//終止對套接字庫的使用
closesocket(m_socket);//關閉套接字,釋放與套接字相關的資源。
4.3.5 程序運行效果如圖1所示
<E:\2008學術交流\2008學術交流第一卷第九期\第1次供稿 54\2網(wǎng)絡通訊及安全\yxy02.tif>
4.3.6 注意問題
編寫網(wǎng)絡通信程序需要特別注意的是:每一臺機器內(nèi)部對變量的字節(jié)存儲順序不同,而網(wǎng)絡傳輸?shù)臄?shù)據(jù)是一定要統(tǒng)一順序的。所以對內(nèi)部字節(jié)表示順序與網(wǎng)絡字節(jié)順序不同的機器,一定要對數(shù)據(jù)進行轉換;在一個套接字上基于消息請求網(wǎng)絡事件通知,可以同時請求多個網(wǎng)絡事件,當接收到到消息時,需要根據(jù)發(fā)生的網(wǎng)絡事件作相應的處理;網(wǎng)絡的狀況瞬息萬變,在調(diào)用函數(shù)的時候,應對函數(shù)的返回值進行判斷,以便找到出錯原因。
5 結論
在Windows平臺下程序的運行都是基于消息的,如果采用阻塞套接字,就會由于接收函數(shù)的調(diào)用而導致程序暫停運行,影響了程序運行的效率。采用異步選擇機制,接收端和發(fā)送端在同一個程序中,并且采用數(shù)據(jù)報套接字實現(xiàn)了局域網(wǎng)通信,達到了簡單、高效、實時的目的。在實現(xiàn)網(wǎng)絡通信時,除了應注意的問題外,還應了解相關的網(wǎng)絡協(xié)議以及程序在Windows平臺下工作的原理,根據(jù)應用的具體需求,才能實現(xiàn)真正高性能的網(wǎng)絡通信。
參考文獻:
[1] 陳明.實用網(wǎng)絡教程[M].北京:清華大學出版社,2006.1.
[2] 胡志坤,秦業(yè),等.Visual C++通信工程實例精解[M].北京:機械工業(yè)出版社,2007.1
[3] 孫小剛,韓冬,等.面向軟件工程的Visual C++網(wǎng)絡程序開發(fā)[M].北京:清華大學出版社,2004,11.
關鍵詞:JAVA;SWING;Socket;IM
中圖分類號:TP319文獻標識碼:A文章編號文章編號:1672-7800(2013)012-0091-03
作者簡介:徐華平(1977-),男,碩士,鹽城師范學院講師,研究方向為教育軟件設計及教育信息化。
0引言
由于企業(yè)內(nèi)管理、生產(chǎn)、銷售等各個環(huán)節(jié)的信息流動與傳遞已成為企業(yè)正常生產(chǎn)與運轉的重要條件,搭建一個基于企業(yè)內(nèi)部網(wǎng)絡的即時通信平臺的重要性不言而喻。然而,通用的商業(yè)IM軟件依賴于互聯(lián)網(wǎng)接入技術,其信息安全性差。因此,有必要建立一種基于局域網(wǎng)的內(nèi)部即時通信平臺。
在各類網(wǎng)絡客戶端之間的通信機制的選擇中,基于Socket機制無疑是成熟、可靠的選擇。這種機制透明于各類局域網(wǎng)絡類型,能夠為企業(yè)提供一種優(yōu)良、高效、快速的通信機制?;谏鲜鰞?yōu)點,使得基于Socket機制的網(wǎng)絡通信軟件無需對企業(yè)現(xiàn)有的網(wǎng)絡硬件設施進行任何變動,因而具有成本低廉的優(yōu)點,能有效降低局域網(wǎng)通信負荷,提高局域網(wǎng)的使用效率,可以很好地解決企業(yè)內(nèi)部局域網(wǎng)的各種通信需求。
1系統(tǒng)關鍵技術分析與選擇
本文重點探討即時通訊軟件設計中實現(xiàn)系統(tǒng)通訊的關鍵技術。在應用系統(tǒng)中,客戶端向服務端發(fā)送請求,等待服務器返回數(shù)據(jù),再刷新客戶端的數(shù)據(jù),稱之為通訊。在B/S或UE設備上實現(xiàn)即時通信的客戶端,其同步方式是不可行的。此類客戶端一方面處理能力弱,另一方面網(wǎng)絡會引起延時,因此,在客戶端之間以及客戶端與服務器之間的同步協(xié)調(diào)難以做到,通常采用異步方式。在 C/S 網(wǎng)絡編程中,數(shù)據(jù)的發(fā)送和接收通過Socket 套接口完成,套接字分為阻塞式和非阻塞式[1]。
通過對Java Net框架下GUI技術、通信協(xié)議等關鍵技術的分析,本通信器決定采用如下技術方案:
(1) Swing技術開發(fā)GUI桌面程序:采用Swing頂層容器、基本組件和事件處理等輕量級組件構建局域網(wǎng)通信系統(tǒng)的程序主要界面。
(2) UDP通信協(xié)議: 鑒于UDP協(xié)議無鏈接,不可靠傳輸,通信雙方可不保持對方的狀態(tài),只需配置端口和IP地址即可通信,方便快捷,減少網(wǎng)絡開銷;考慮到UDP協(xié)議不可靠性,該通信器的通信協(xié)議中采用了確認與重傳機制來保證數(shù)據(jù)傳輸?shù)目煽啃?,采用了動態(tài)的超時重傳定時器值提高了本協(xié)議的適應性和靈活性,還使用了在應用層對數(shù)據(jù)進行分片的方法來避免IP層分片的低效率[2]。
(3) 在本系統(tǒng)設計采用UDP通信協(xié)議時,基于UDP的Socket編程技術,中提供了兩個類DatagramSoeket和DatagramPacket用來支持數(shù)據(jù)報通信。Datagramsocket用來在程序之間建立傳送數(shù)據(jù)報的通信連接是數(shù)據(jù)報通信中的Socket。在數(shù)據(jù)報實現(xiàn)C/S通信程序時,無論在客戶端還是服務器端,都要首先建立一個DatagramSoeket對象,用來表示數(shù)據(jù)報通信的端點,應用程序通過Socket接收或發(fā)送數(shù)據(jù)報。DatagramPaeket則用來表示一個數(shù)據(jù)報,它是傳輸數(shù)據(jù)的載體,封裝了數(shù)據(jù)、數(shù)據(jù)長度、數(shù)據(jù)報地址等信息[3]。
(4)系統(tǒng)采用Derby作為數(shù)據(jù)庫,Derby數(shù)據(jù)庫是一個純用Java實現(xiàn)的內(nèi)存數(shù)據(jù)庫,屬于Apache的開源項目。因為是用Java實現(xiàn)的,所以可以在任何平臺上運行。另外一個特點是體積小、免安裝,只需要幾個小Jar包就可以運行。
2系統(tǒng)總體目標與需求分析
2.1設計目標
(1)使用Swing組件實現(xiàn)圖形化用戶界面。
(2)使用Socket技術和UDP協(xié)議通過IP地址和PORT提供不可靠非連接通信。
(3) 實現(xiàn)基于線程池的多端口監(jiān)聽。
(4) 實現(xiàn)客戶端間的文字、文件信息共享。
2.2功能需求分析
(1)用戶管理。即時通訊系統(tǒng)擁有多個賬戶,允許多個用戶注冊。一個用戶可以注冊多個標識,注冊所使用的帳號類型為字母數(shù)字的組合。注冊新用戶時必須填寫符合要求的信息,注冊后只有用戶名與密碼驗證成功才能正確登錄。
(2)分組管理。分組管理部分要能夠實現(xiàn)分組的添加與刪除,所添加的分組名稱可以是中文也可以是字母數(shù)字的組合,通過對分組的有效管理便于更方便地管理好友。
(3)好友管理。用戶可以查詢所有用戶,適當選擇加為好友。一個用戶可以添加多個用戶為好友,同時一個用戶也可以被多個用戶添加為好友。用戶可以刪除好友,但是用戶只可以將好友放在一個組中。
(4)即時通訊。即時通訊模塊用戶可以與在線的好友進行聊天,用戶首先查看好友是否在線,如果在線即可進行即時通訊,并且用戶可以查看與好友的所有聊天記錄。
2.3數(shù)據(jù)庫設計
根據(jù)數(shù)據(jù)邏輯結構設計的情況,本系統(tǒng)數(shù)據(jù)庫的數(shù)據(jù)表共有好友數(shù)據(jù)表、用戶表、分組表3個,和一般數(shù)據(jù)庫應用系統(tǒng)基本類似,這里不再贅述。
3系統(tǒng)的設計與實現(xiàn)
(1)用戶列表模塊。
該模塊實現(xiàn)本局域網(wǎng)內(nèi)平臺中當前登錄用戶的列表顯示,并顯示當前用戶通過搜索或好友添加功能添加的用戶。在每個用戶節(jié)點上右擊鼠標,會出現(xiàn)Popup功能菜單項,其中菜單項的添加好友和刪除好友都會控制好友列表節(jié)點的增加和刪除。關鍵代碼部分如下:
……
add(p,BorderLayout.NORTH);
add(new JScrollPane(table),BorderLayout.CENTER);
setBounds(100,100,200,600);
setVisible(true);
validate();
thread.start();
模塊說明:
本模塊主要采用了Swing技術、多線程技術和循環(huán)技術。在系統(tǒng)進程啟動時,利用多線程技術啟動線程循環(huán)——自動檢測數(shù)據(jù)庫已有好友數(shù)據(jù)信息,然后使用Swing提供的JTree類對象生成一個分層顯示數(shù)據(jù)的視圖即用戶列表。JTree類中的基本對象叫作結點,它表示在給定層次結構中的數(shù)據(jù)項。樹以垂直方式顯示數(shù)據(jù),每行顯示一個節(jié)點。每個樹中只有一個根節(jié)點,其他節(jié)點從根節(jié)點引出。除根節(jié)點外,其他節(jié)點分為兩類:一類是帶子節(jié)點的分支節(jié)點;另一類是不帶子節(jié)點的葉節(jié)點。樹節(jié)點由Javax.swing.tree包中的接口TreeNode來定義的,該接口被DefaultMutableTreeNode類實現(xiàn)。為了創(chuàng)建一個樹,使用DefaultMutableTreeNode類為樹創(chuàng)建節(jié)點。
通過建立一個存放用戶姓名的標簽對象Lable,該標簽顯示的內(nèi)容由用戶在登錄時在登陸界面輸入的用戶名信息來確定,另外創(chuàng)建一個標簽來存放“在線列表”,然后實質(zhì)上存放在線列表里面的內(nèi)容則有一個表格組件來存放所對應的在線用戶,通過UDP數(shù)據(jù)報廣播來獲取在線的用戶的姓名以及IP地址,然后將數(shù)組的數(shù)據(jù)導入表格組件中,就可以形成在線用戶列表。
(2)聊天功能模塊。
用戶通過單擊在線用戶列表中的節(jié)點選擇某一用戶頭像,即可觸發(fā)聊天對話框界面。聊天對話框的左上部分為顯示聊天記錄。左下方為聊天輸入框。右側可以顯示對方的用戶名和IP等信息。本次聊天內(nèi)容在窗口關閉時,重新打開后仍會保存,一旦整個系統(tǒng)重啟之后,上次的聊天內(nèi)容才會清除。
關鍵代碼如下:
……
con.add(new JScrollPane(inMessage),BorderLayout.CENTER);
con.add(p,BorderLayout.SOUTH);
Thread thread=new Thread(this);
……
模塊說明:在用戶聊天界面上分別創(chuàng)建一個既用于接收信息又用于發(fā)送信息的多行純文本域對象JtextArea,它們來分別存放要發(fā)送的信息和聊天信息。outMessage用來存放所要發(fā)送的數(shù)據(jù),而inMessage用來存放聊天的信息。
(3)用戶搜索功能模塊。
搜索在線用戶的設計是基于廣播數(shù)據(jù)報的,通過采用組播地址然后創(chuàng)建廣播套接字,設置一個廣播的范圍,在這里設置的是一個本地的局域網(wǎng)的范圍。設置了廣播范圍之后加入廣播組,就可以廣播數(shù)據(jù)報和接收廣播數(shù)據(jù)報。
關鍵代碼如下:
……
group=InetAddress.getByName("10.192.168.0");
socket=new MulticastSocket(port);
socket.setTimeToLive(255);
socket.joinGroup(group);
和多數(shù)通行通信軟件一樣,發(fā)送端在某一端口廣播數(shù)據(jù),接收端在指定的端口或端口范圍內(nèi)偵聽并接收廣播數(shù)據(jù)。
DatagramPacket packet=null;
byte data[]=total.getBytes();
packet=new DatagramPacket(data,data.length,group,port);
System.out.println(new String(data));
socket.send(packet);
……
這里的Packet是某一進程中待發(fā)送的數(shù)據(jù)報,定義一個數(shù)組用來存放,并且設置了長度length,還有端口號port,最后通過socket在本地的局域網(wǎng)上進行廣播數(shù)據(jù)報。通過廣播自己的IP地址,讓所有在線的用戶接收到自己的IP地址并且添加到對方的在線列表中,這樣每一個用戶的一個廣播就使得列表可以更新。
(4)點對點資源共享功能模塊。
如上所述,為了保證系統(tǒng)通信的即時性,選擇的是使用UDP數(shù)據(jù)報的一個點對點的通信方式,實現(xiàn)了兩個客戶端間進程間的通信,這里使用DatagramPacket方法創(chuàng)建數(shù)據(jù)報對象:
DatagramPacket(b,b.length,address,8604);//發(fā)送端口是8604
DatagramSocket mail=new DatagramSocket();
通過DatagramPacket為存放指定數(shù)據(jù)的數(shù)據(jù)報,其中包括了指定的數(shù)據(jù),數(shù)據(jù)接收方的信息,并且要明確發(fā)送的目的地址address,同時指定偵聽該通信的主機端口號為8604。而在接收的時候:
byte b[]=new byte[5120];
mail.receive(pack);
構建一個長度為5 120字節(jié)的數(shù)組用于保存接收到的數(shù)據(jù),同時設計了一個參數(shù)Pack,可以把收到的通信數(shù)據(jù)報傳遞給參數(shù)Pack。
4結語
本通信器界面友好, 雖然與大型復雜即時通訊軟件相比在功能上還稍有欠缺, 但是其作為即時通訊的主體功能已經(jīng)具備,尤其是其難易程度適中,綜合運用了Java 面向對象的多種知識,是高等院校《網(wǎng)絡編程》課程的一個很好的實例。
當然由于諸多條件的制約,以及系統(tǒng)設計的定位,該設計在文件傳輸多樣化、網(wǎng)絡適應性、通信機制、數(shù)據(jù)存儲與共享方面仍然存在較多不足,主要有以下幾個方面:
(1) 實現(xiàn)多樣化文件傳輸,如:圖片、文檔、音頻、視頻等。
(2) 初期對系統(tǒng)所采用數(shù)據(jù)庫的通用性認識不足,后期可以采用Mysql或XML等主流數(shù)據(jù)存儲技術,使得系統(tǒng)具有更強的適應性。
(3) 改進系統(tǒng)通信協(xié)議,考慮穿透防火墻、異構網(wǎng)絡實現(xiàn)多局域網(wǎng)之間的通信。
(4) 用戶界面應借鑒主流IM軟件,實現(xiàn)良好的用戶體驗。
(5) 如果作為一個高性能企業(yè)內(nèi)部即時通信軟件,應考慮到大用戶、多并發(fā)的情況,應盡可能減輕服務器負荷,盡可能地將一些處理、判斷放在客戶端進行,節(jié)約服務器端開銷。
參考文獻參考文獻:
[1]陳立浩. 基于B/S和C/S的即時通信系統(tǒng)[J].計算機工程, 2009(15).
關鍵詞:winsock;TCP/IP協(xié)議;計費管理系統(tǒng)
Winsock是一個ActiveX控件,它為采用客戶機/服務器通信機制的網(wǎng)絡提供了編制接口,使客戶機端和服務器端藉此實現(xiàn)連接和數(shù)據(jù)交換。它不是一種網(wǎng)絡協(xié)議,而是一套開放的、支持多種協(xié)議的Windows下的網(wǎng)絡編程接口。Socket實際在計算機中提供了一個通信端口,可以通過這個端口與任何一個具有Socket接口的計算機通信。應用程序在網(wǎng)絡上傳輸,接收的信息都通過這個Socket接口來實現(xiàn)。
本文主要研究了Winsock的工作原理、編程方法,TCP/IP協(xié)議下計算機的工作原理,基于TCP/IP協(xié)議的網(wǎng)絡編程,服務器端與客戶機端程序的設計等,通過解決這些問題來實現(xiàn)Winsock網(wǎng)絡按時收費系統(tǒng)的設計。
一、系統(tǒng)設計方案的研究
我們所設計的網(wǎng)絡計費系統(tǒng)分為三部分,一是在win32平臺上的線程對數(shù)據(jù)包的截獲,并且進行初步的整理,生成日志文件,作為前臺;而后臺則是在windows net server上的數(shù)據(jù)庫管理,直接取得第一部分截取程序生成的日志文件和通過ftp獲取在Linux服務器上其它服務生成的日志文件,對其分析,并至于以BDE驅動的數(shù)據(jù)庫文件中。三是計費信息用戶查詢子系統(tǒng),使得用戶能在線通過權限查詢到自己各個時間段內(nèi)的計費信息和費用情況,有利于減輕網(wǎng)絡管理員的工作負擔。
Socket有3種主要類型:流式套接口,數(shù)據(jù)報套接口和原始套接口。面向連接服務器處理的請求往往比較復雜,原理是:服務器端不斷監(jiān)聽客戶端的請求,當客戶端向服務器端發(fā)出連接請求并被服務器端檢測到以后,服務器會接收客戶端的請求,并建立連接。本文在方案選擇上采用了在網(wǎng)絡編程中最常用的一種模型--客戶機/服務器模型。選取了基于TCP/IP的客戶機/服務器模型和面向連接的流式套接字。
二、系統(tǒng)的軟件設計
(一)服務器的設計
①在初始化階段調(diào)用WSAStartup(),此函數(shù)在應用程序中初始化Windows Sockets DLL ,只有此函數(shù)調(diào)用成功后,應用程序才可以再調(diào)用其他Windows Sockets DLL中的API函數(shù)。②建立Socket,初始化WinSock的動態(tài)連接庫后,需要在服務器端建立一個監(jiān)聽的Socket,為此可以調(diào)用Socket()函數(shù)用來建立這個監(jiān)聽的Socket,并定義此Socket所使用的通信協(xié)議。③綁定端口,為服務器端定義的這個監(jiān)聽的Socket指定一個地址及端口(Port),這樣客戶端才知道待會要連接哪一個地址的哪個端口,為此我們要調(diào)用bind()函數(shù),該函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。④監(jiān)聽,當服務器端的Socket對象綁定完成之后,服務器端必須建立一個監(jiān)聽的隊列來接收客戶端的連接請求。listen()函數(shù)使服務器端的Socket 進入監(jiān)聽狀態(tài),并設定可以建立的最大連接數(shù)。⑤服務器端接受客戶端的連接請求,當Client提出連接請求時,Server端hwnd視窗會收到Winsock Stack送來我們自定義的一個消息,這時,我們可以分析lParam,然后調(diào)用相關的函數(shù)來處理此事件。⑥結束 socket 連接,這一過程可以由服務器或客戶機的任一端啟動,只要調(diào)用closesocket()就可以,而要關閉Server端監(jiān)聽狀態(tài)的socket,同樣也是利用此函數(shù)。
(二)客戶機的設計
①建立客戶端的Socket,客戶端應用程序首先也是調(diào)用WSAStartup() 函數(shù)來與Winsock的動態(tài)連接庫建立關系,然后同樣調(diào)用socket() 來建立一個TCP或UDP socket(相同協(xié)定的 sockets 才能相通,TCP 對 TCP,UDP 對 UDP)。與服務器端的socket 不同的是,客戶端的socket 可以調(diào)用 bind() 函數(shù),由自己來指定IP地址及port號碼;但是也可以不調(diào)用 bind(),而由 Winsock來自動設定IP地址及port號碼。②提出連接申請,客戶端的Socket使用connect()函數(shù)來提出與服務器端的Socket建立連接的申請,函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。
三、基于TCP/IP協(xié)議的網(wǎng)絡編程
TCP/IP協(xié)議實際上就是在物理網(wǎng)上的一組完整的網(wǎng)絡協(xié)議。其中TCP是提供傳輸層服務,而IP則是提供網(wǎng)絡層服務。
TCP/IP協(xié)議的核心部分是傳輸層協(xié)議(TCP、UDP),網(wǎng)絡層協(xié)議(IP)和物理接口層,這三層通常是在操作系統(tǒng)內(nèi)核中實現(xiàn),因此用戶一般不涉及。編程時,編程界面有兩種形式:一是由內(nèi)核心直接提供的系統(tǒng)調(diào)用;二是使用以庫函數(shù)方式提供的各種函數(shù)。前者為核內(nèi)實現(xiàn),后者為核外實現(xiàn)。用戶服務要通過核外的應用程序才能實現(xiàn),所以要使用套接字(socket)來實現(xiàn)。
四、系統(tǒng)測試包括測試儀器和軟件調(diào)試測試儀器
Agilent網(wǎng)絡測試儀表和AutoRunner自動化軟件測試工具。軟件調(diào)試:由于本系統(tǒng)要實現(xiàn)的功能比較多,所以在編寫程序和調(diào)試時出現(xiàn)了許多問題,不過經(jīng)過多次反復的調(diào)試后還是能把題目所要實現(xiàn)的功能都能實現(xiàn)了。
五、結束語
基于Winsock的編程,可以比較容易的實現(xiàn)按時收費系統(tǒng)的設計。利用Winsock編程的系統(tǒng)界面友好、操作簡便、功能全面。這也就說明Winsock編程的優(yōu)點,它將會成為軟件開發(fā)的重要工具!
參考文獻:
【關鍵詞】I/O NIO BIO SOCKET通信 Java 多線程
1 引言
傳統(tǒng)BIO技術在Socket通信中,系統(tǒng)需要為每一個鏈接建立一個線程去處理其請求,隨著客戶端的并發(fā)量不斷增加后,會導致線程數(shù)量的增加嚴重影響系統(tǒng)的性能。由于并發(fā)量的增加有可能導致服務器宕機,嚴重影響到用戶在使用過程中的良好體驗。為解決傳統(tǒng)BIO的不足,Java 中提供了新的API----NIO和NIO2來解決由于BIO技術帶來的系統(tǒng)瓶頸問題。在NIO中系統(tǒng)不再為每一個用戶請求注冊一個線程,而是通過通道將每一個鏈接都注冊到多路復用器上,通過多路復用器對注冊在其上的鏈接進行輪詢檢查,發(fā)現(xiàn)有鏈接請求才會開啟線程對其進行處理。NIO只在有連接請求時selector才會不斷輪詢檢查通道IO操作是否完成,與NIO技術不同的是AIO技術是異非步阻塞的。AIO中不再需要多路復用器,而是由異步非阻塞通道直接操作read和write方法。在客戶端讀寫請求發(fā)出后不再等待服務器的響應,而是處理完成后由操作系統(tǒng)來通知應用程序。AIO與NIO這兩種技術都極大地改變了傳統(tǒng)I/O流的不足。
2 Socket基本通信原理介紹
Socket是網(wǎng)絡通信中的其中一方,用來接收網(wǎng)絡通信中雙方其中一方的請求,方便的對雙方的數(shù)據(jù)進行傳輸。Socket通信分有連接的和無連接,面向連接的Socket通信與面向非連接的Socket通信相比有更高的可靠性和更有效的數(shù)據(jù)傳輸。本文基于有連接的套接字傳輸。
3 BIO、NIO、AIO技術比較
3.1 BIO技術簡介
BIO技術同步并且阻塞,在這種情況下,服務器需要為每一個連接開啟一個線程,只要有客戶端有請求服務器就需要開啟線程去進行處理。從客戶端傳來的每個請求,服務器都需要為其創(chuàng)建相應的線程去處理其請求。在BIO中,由于其線程的開銷很大,適合于運用在并發(fā)量小的場景下。其基本模型如圖1所示。
BIO網(wǎng)絡通信基本步驟:
3.1.1 服務低端
(1)創(chuàng)建ServerSocket并綁定監(jiān)聽端口;
(2)創(chuàng)建Socket用來接收客戶端請求;
(3)創(chuàng)建輸入輸出流用來接收客戶端輸入或向客戶端輸出數(shù)據(jù);
(4)關閉輸入輸出流等系統(tǒng)資源。
3.1.2 客戶端
(1)創(chuàng)建Socket綁定IP地址及端口;
(2)創(chuàng)建輸入輸出流用來接收服務器端相應或向服務器端發(fā)送數(shù)據(jù);
(3)關閉輸入輸出流等系統(tǒng)資源。
3.2 NIO技術簡介
NIO技術即New IO技術,NIO技術由很多類和組件構成,其最重要的由channel、Buffer、和Selectors三個核心部分組成。
Channel:Java NIO中的通道類似于流,但又不完全相同。既可以從通道中讀取數(shù)據(jù)到Buffer也可以將數(shù)據(jù)從Buffer寫入通道中。其中SocketChannel和ServerSocketChannel是NIO中提供的用來解決Socket通信中的服務器性能問題的。SocketChannel通過TCP協(xié)議來讀取網(wǎng)絡中的數(shù)據(jù),ServerSocketChannel用來接收鏈接來的請求以供服務器相應。
Buffer:Buffer是用來為數(shù)據(jù)提供緩沖區(qū)的。在NIO技術中,所有的數(shù)據(jù)都必須經(jīng)過緩沖區(qū)。緩沖區(qū)本質(zhì)上為一塊可讀可寫的內(nèi)存塊,NIO中提供了不同數(shù)據(jù)類型的緩沖區(qū)來處理不同的數(shù)據(jù)請求,和一些基本的方法來操作緩沖區(qū)中的數(shù)據(jù)。
Selector:Selector是單線程來處理多個鏈接請求的關鍵。在Socket通信中,如果將多個鏈接請求注冊到多路復用器上,就可以用一個線程來處理多個鏈接請求,這樣就提高了Socket通信的效率。NIO通信中的網(wǎng)絡模型
如圖2所示。
NIO通信基本步驟:
3.2.1 服務器端
(1)創(chuàng)建多路復用器Selector 用來選擇通道;
(2)創(chuàng)建服務器端通道ServerSocketChannel;
(3)為多路復用器上注冊ServerSocketChannel用來將數(shù)據(jù)通過通道讀寫;
(4)申請Buffer存儲數(shù)據(jù);
(5)多路選擇器通過其key值輪詢檢查通道讀寫B(tài)uffer中的數(shù)據(jù)完成其通信過程。
3.2.2 客舳
(1)創(chuàng)建IP地址和端口號對應的SocketChannel ;
(2)將SocketChannel設置為非阻塞模式;
(3)創(chuàng)建多路復用器Selector注冊SocketChannel到多路選擇器;
(4)多路選擇器輪詢檢查通道從Buffer中讀寫數(shù)據(jù)。
在NIO網(wǎng)絡通信模型中,客戶端向服務器端發(fā)起鏈接請求,客戶端將數(shù)據(jù)寫入服務器端Buffer中,然后通過channel來從Buffer讀取數(shù)據(jù)或向Buffer寫入數(shù)據(jù),對于通道中的數(shù)據(jù)必須經(jīng)過選擇器來向服務器端的線程發(fā)起請求。而每一個多路選擇器對應一個線程模型,這樣一來,只有當鏈接請求有效時服務器才為客戶端開啟線程處理數(shù)據(jù)。對于同步阻塞的NIO模型中客戶端在向服務器端發(fā)送完數(shù)據(jù)后會不斷詢問I/O操作是否就緒才能進行下一步的操作。此模型中由于不需要為每一個鏈接請求創(chuàng)建一個線程,大大減少了線程之間的切換帶來的巨大開銷。提高了I/O的效率,使得在socket網(wǎng)絡通信更加高效。但由于NIO在鏈接請求中會不斷詢問I/O操作是否完成,其適合運用在短鏈接且并發(fā)量大的場合下。
3.3 AIO技術簡介
AIO即為異步非阻塞IO,與NIO不同的是,在這種模式下,客戶端發(fā)起一個鏈接請求后不在詢問服務器端的I/O操作是否完成便立即返回。在使用過程中只需直接調(diào)用異步的read和write方法來讀寫數(shù)據(jù),在讀寫過程完畢后由操作系統(tǒng)主動通知應用程序讀寫操作是否完成。由AIO的讀寫過程可以看出,因為在讀寫完成后客戶端不需要再詢問服務器端是完成了I/O操作,所以AIO非常適合于運用在那些并發(fā)量大且長連接的請求。AIO模型如圖3所示。
AIO中有幾個比較重要的類:
AsynchronousServerSocket:用來創(chuàng)建服務器端的ServerSocket并綁定地址監(jiān)聽端口。
AsynchronousSocketChannel:Socket在異步非阻塞通信中的應用,用來表示一個連接請求,并用來在通信過程中傳遞數(shù)據(jù)。
AsynchronousChannelGroup:異步通道的分組管理,目的是問了資源共享。創(chuàng)建AsynchronousChannelGroup時需要為其綁定一個線程執(zhí)行器對象,這個線程池主要完成兩個任務:處理I/O事件和派發(fā)CompletionHandler。在創(chuàng)建AsynchronousServerSocket時需要為其綁定一個AsynchronousChannelGroup。通過AsynchronousServerSocket創(chuàng)建的AsynchronousChannelGroup將屬于同一組,共享其中資源。
CompletionHandler:用于定義在異步IO操作完成后的回調(diào)接口。
3.3.1 服務器端
(1)創(chuàng)建AsynchronousChannelGroup;
(2)創(chuàng)建AsynchronousServerSocketChannel并將它綁定在AsynchronousChannelGroup上;
(3)為AsynchronousServerSocketChannel對象綁定端口號;
(4)調(diào)用accept()接收客戶端請求實現(xiàn)CompletionHandler接口調(diào)用讀寫方法進行讀寫數(shù)據(jù)。
3.3.2 客戶端
(1)創(chuàng)建AsynchronousSocketChannel;
(2)綁定IP地址和端口號鏈接服務低端實現(xiàn)CompletionHandler接口中方法直接進行讀寫數(shù)據(jù)。
3.4 各種I/O技g比較分析
BIO:同步阻塞I/O,使用難度簡單,可靠性低,適用于鏈接并發(fā)量小的架構且對服務器資源依賴更高。
NIO:同步非阻塞I/O,使用難度復雜,可靠性高,適用于并發(fā)量大且鏈接較短的場景。
AIO:異步非阻塞I/O,使用難度一般,可靠性高,適用于并發(fā)量大且鏈接長的場景。
4 結語
傳統(tǒng)網(wǎng)絡在IO處理方面存在著性能不足的問題,NIO與AIO包的引入解決了傳統(tǒng)IO性能瓶頸問題,使的Java在網(wǎng)絡通信中有了更搞得效率。對于不同的IO來說,它們各自有有不同的應用領域。對于那些并發(fā)量小,數(shù)據(jù)傳輸量小的場景來說,傳統(tǒng)的BIO完全可以勝任其工作。相反對于那些對性能要求比較高,并發(fā)量大且對IO的要求比較搞得場合來說應該選擇NIO或者BIO技術。如果客戶端與服務器在長連接的情況下選擇AIO相比NIO會更加高效一些。相反,如果是短連接的應用領域,則推薦使用NIO。
參考文獻
[1]范寶德,馬建生.Java非阻塞通訊研究[J].微計算機信息,2006,22(12-3):116-119.
[2]劉邦桂,李正凡.用Java實現(xiàn)流式Socket通訊[J].華東交通大學學報,2007,24(05):110-112.
[3]封瑋,周世平.基于Java NIO的非阻塞通信的研究與實現(xiàn)[J].計算機系統(tǒng)應用,2004(09):32-35.
[5]任小強,陳金鷹,李文彬,胡波.網(wǎng)絡通信之Java Socket多線程通信[J].信息通信,2015(06):206-207.
作者簡介
王少輝(1992-),男,山西省平順縣人。碩士學位?,F(xiàn)為山東大學(威海)機電與信息工程學院學生。主要研究方向為電路與系統(tǒng)。
陳曉鵬(1992-),男,天津市人。碩士學位?,F(xiàn)為山東大學(威海)機電與信息工程學院學生。主要研究方向為電路與系統(tǒng)。
關鍵詞:語音集群通信;移動網(wǎng)絡;SSL Socket;opus
中圖分類號:TP393 文獻標識碼:A 文章編號:1009-3044(2016)27-0014-04
Abstract: The paper analyzes the specific business demands and technical requirements of the industry users in the voice cluster communication, and gives a solution of voice cluster communication system for the mobile network environment. It designs the underlying transmission framework based on SSL Socket secure link and data transmission format, puts forward the basic method to establish interactive applications, according to the features of mobile network environment, it analyzes and uses the reasonable audio codec library, designs audio mixing algorithm, solves the core problem of the voice cluster communication system.
Key words: voice cluster communication; mobile network; SSL Socket; opus
隨著公共網(wǎng)絡服務和多媒體通信技術的發(fā)展,利用移動終端進行語音實時通信已成為民用市場或行業(yè)應用的熱門業(yè)務[1]。相比較傳統(tǒng)的電話語音業(yè)務,基于IP網(wǎng)絡的語音通信系統(tǒng)具有跨地域、低成本、高質(zhì)量、可定制等優(yōu)勢,且隨著移動網(wǎng)絡建設的不斷升級,語音通信系統(tǒng)的通話效果和時延已與電話語音的差別不大。目前,市場上主流的語音通信應用有兩類:一是采用頻道、群組或聊天室形式的多人語音通信,如yy語音、qt語音等;二是采用一對一通話模式的IP網(wǎng)絡電話,如Skype等。微信作為國內(nèi)影響力較大的即時通信軟件,也提供了一對一的實時語音功能。
對于滿足專有行業(yè)或企業(yè)的語音集群通信業(yè)務[2],通常還需要考慮以下需求:1)群組通話是集群通信的主要業(yè)務模式,具有群組信道共享,避免通信互擾等服務要求;2)對于室外作業(yè)多采用移動網(wǎng)絡,而非連接到有線網(wǎng)絡共享的AP熱點,網(wǎng)絡質(zhì)量受限。3)VPDN專網(wǎng)服務支持或其他網(wǎng)絡安全要求;4)在語音業(yè)務基礎上,提供文本通信、文件傳輸?shù)榷ㄖ乒δ埽?)對語音、文本、共享文件等關鍵信息的私有存儲或全業(yè)務存儲。因此,在設計開發(fā)基于移動網(wǎng)絡的語音集群通信系統(tǒng)時,應充分考慮行業(yè)應用特點,預留必要的業(yè)務應用接口。
1 基本傳輸框架
語音集群通信系統(tǒng)基于標準的客戶端-服務器通信模型設計??蛻舳伺c服務器之間的數(shù)據(jù)傳輸采用TCP/UDP兩種協(xié)議,分別適用不同的網(wǎng)絡環(huán)境。當移動網(wǎng)絡質(zhì)量較好時,可以根據(jù)設置使音頻數(shù)據(jù)通過TCP通道傳輸,保證通話語音的完整性和可靠性;當網(wǎng)絡條件較差時,使用UDP通道傳輸可以避免TCP傳輸多次握手導致的網(wǎng)絡擁塞,實現(xiàn)低延時傳輸,保證系統(tǒng)的可用性。語音通信過程中的控制信令和通信信令則是基于TCP協(xié)議可靠傳輸[3]。
1.1 構建安全通道
安全套接層(Secure Socket Layer,SSL)是Netscape公司研發(fā)的用于在IP網(wǎng)絡上實現(xiàn)數(shù)據(jù)安全傳輸?shù)膶S袇f(xié)議,通過數(shù)據(jù)加密技術確保數(shù)據(jù)在網(wǎng)絡傳輸過程中不會被截取及竊聽。SSL及其后續(xù)發(fā)展的傳輸層安全(Transport Layer Security,TLS)提供了傳輸層的數(shù)據(jù)完整性保護,包括身份認證、協(xié)商加密算法、交換加密密鑰等[4]。OpenSSL是互聯(lián)網(wǎng)上適用性最廣泛的SSL密碼庫之一,提供了多種編程語言的庫支持。本系統(tǒng)引入OpenSSL 1.0.2方法庫,將TCP Socket替換為SSL Socket,對傳輸層協(xié)議進行鏈路安全保護[5]。
SSL Socket的建立流程是:
1)客戶端請求建立SSL Socket連接,并向服務器發(fā)送SSL版本、加密參數(shù)等必要信息。服務器返回自身的SSL版本、加密參數(shù)、安全證書等必要信息??蛻舳讼蚍掌魈峁┱J證證書。
2)客戶端驗證服務器證書后,生成pre-master secret,并用公鑰加密后發(fā)送給服務器。服務器對證書進行認證,通過后用私鑰解密pre-master secret,并生成master secret。
3)通信雙方通過master secret生成會話密鑰,完成SSL Socket的創(chuàng)建,之后的通信數(shù)據(jù)將通過會話密鑰加密傳輸。在本系統(tǒng)中,會話密鑰采用TLSv1 AES256-SHA加密。
由于UDP是面向無連接的傳輸協(xié)議,為保證數(shù)據(jù)傳輸安全,在發(fā)送函數(shù)sendto()之前加入encrypt(),這里可采用與TLSv1 AES256-SHA強度相當?shù)募用芩惴ㄟM行數(shù)據(jù)加密。接收側在recvfrom()之后加入decrypt(),進行數(shù)據(jù)解密。
1.2 數(shù)據(jù)傳輸格式
本系統(tǒng)的數(shù)據(jù)報文格式如圖1所示??蛻舳伺c服務器之間遵循此格式發(fā)送交互信息,其中報文頭Ptrfix包含1個字節(jié)的類型信息,區(qū)別信令數(shù)據(jù)或語音數(shù)據(jù),提供長度信息進行組包校驗。載荷部分Data為實際交互數(shù)據(jù),采用TLSv1 AES256-SHA或其他算法加密。由于UDP協(xié)議僅用于發(fā)送語音數(shù)據(jù),其數(shù)據(jù)傳輸格式為圖1的Payload部分,最大長度為UDP分片的理論最大長度65507B[6]。
2 應用流程
2.1 用戶接入
本系統(tǒng)的接入流程如圖2所示,主要包括:
1)建立連接:客戶端向服務器請求建立用于控制信令和TCP數(shù)據(jù)通信的SSL Socket長連接。
2)版本確認:客戶端與服務器相互發(fā)送版本信息,包括軟件版本、操作系統(tǒng)版本、其他備注信息等,雙方根據(jù)版本判斷系統(tǒng)訪問的兼容性。
3)用戶登錄:客戶端向服務器發(fā)送登錄認證信息,包括登錄賬戶、登錄密碼,或是用于登錄認證的證書信息。
4)密鑰交換:該步驟為可選項,由于SSL Socket完成了TCP連接的密鑰交換,如系統(tǒng)支持UDP傳輸,則需要服務器發(fā)送UDP加密的密鑰信息給客戶端。
5)群組信息:服務器向請求登錄的客戶端發(fā)送群組的狀態(tài)信息,包括群組ID、名稱、描述、拓撲關系,以及群組中用戶的在線狀況和當前狀態(tài)。
6)用戶信息:服務器向其他客戶端發(fā)送新登錄用戶的狀態(tài)信息,通知該用戶已上線。
7)心跳信息:客戶端完成基本登錄流程,通過發(fā)送周期性的心跳報文,維持長連接狀態(tài)。根據(jù)實際網(wǎng)絡狀況可調(diào)整心跳報文的發(fā)送周期,如部署地域的網(wǎng)絡狀態(tài)較好,可采用3至5秒的發(fā)送間隔。
2.2 信息響應
作為集群通信系統(tǒng),信息響應的基本單位是群組。每個群組的數(shù)據(jù)處理和信息狀態(tài)相對于其他群組保持獨立,即群組之間的數(shù)據(jù)和資源是隔離的,這里通過建立用戶信息的HashMap結構hmUsers和群組信息的HashMap結構hmGroups進行數(shù)據(jù)調(diào)用和處理。調(diào)用用戶或群組對象時,需通過ReadWriteLock進行資源鎖定,保護線程安全[7]??紤]到多線程存在資源切換和鎖定的開銷,在設計上主要對不同類型或分組的任務建立線程,如圖3所示。其中:
1)接收線程主要響應網(wǎng)卡資源,監(jiān)聽服務端口,接收由客戶端發(fā)送的業(yè)務數(shù)據(jù)或信令信息,如果是心跳消息,則直接返回響應;否則,將通過hmUsers和hmGourps查找所屬群組,并將數(shù)據(jù)推送到指定群組的消息緩沖區(qū)中。
2)處理線程主要響應和實現(xiàn)具體業(yè)務。每個群組對象在實例化過程中都會創(chuàng)建本群組的處理線程和數(shù)據(jù)緩沖區(qū),通過提取緩沖區(qū)中的數(shù)據(jù)并解析,線程將信令或其他業(yè)務數(shù)據(jù)交給業(yè)務響應函數(shù)處理,語音數(shù)據(jù)交給數(shù)據(jù)響應函數(shù)處理,并將處理后的數(shù)據(jù)發(fā)送給指定客戶端。在處理線程中,可分模塊響應語音業(yè)務以外的請求,對預留接口進行功能實現(xiàn)。
3)存儲線程主要響應數(shù)據(jù)I/O操作。本系統(tǒng)對獨占性的I/O操作采用單線程序列化處理,即所有群組的語音數(shù)據(jù)通過統(tǒng)一的緩沖序列順序解碼、混音和寫入文件,降低線程切換的開銷。為提高I/O讀寫效率,語音數(shù)據(jù)不會立即寫入文件,而是積累時長2秒(可根據(jù)實際情況配置)的數(shù)據(jù)包后批量寫入。
3 語音處理
3.1 音頻編解碼器選型
目前,國內(nèi)4G LTE網(wǎng)絡建設日趨完善,基于移動網(wǎng)絡的語音通信技術已擺脫GSM時期小于16kbps的窄帶傳輸限制。在音頻編解碼技術選型上,更多考慮的是適應16kbps到64kbps區(qū)間的高品質(zhì)音頻編解碼算法。
本系統(tǒng)主要對Opus、Speex、AMR-WB和G.722.1四種編解碼方案進行比較。Opus是在Skype的SILK編解碼器和的CELT編解碼器基礎上發(fā)展的開源編解碼方案,已形成RFC 6716標準,具有靈活的帶寬適應性。Speex是基于CELP發(fā)展的音頻編解碼方案,但根據(jù)Speex官網(wǎng)提示,Opus的性能已在各方面優(yōu)于Speex。AMR-WB(G.722.2)被廣泛應用在WCDMA的話音業(yè)務上,其VBR特性可以較好的適應網(wǎng)絡帶寬變化。G.722.1提供了優(yōu)于G.722的24kbps和32kbps音頻編碼壓縮。
根據(jù)Opus-Codec給出的音頻編碼質(zhì)量統(tǒng)計對比(圖4),以及兩份Google組織的主觀評測報告[9][10],在同等比特率條件下,Opus編碼能夠達到或超過AMR-WB、G.722.1的編碼質(zhì)量。且考慮到國內(nèi)各地區(qū)移動網(wǎng)絡的傳輸質(zhì)量差異較大,支持6kbps到510kbps比特率和VBR技術的Opus編解碼器可為不同網(wǎng)絡環(huán)境提供更穩(wěn)定的語音通話效果。
3.2 Opus編解碼實例
Opus是基于C語言編寫的音頻編解碼器,Windows平臺可直接加載Opus源代碼進行函數(shù)調(diào)用,Android平臺還需要對源代碼進行NDK編譯,生成供Java語言調(diào)用的so庫。
使用Opus進行語音編碼的代碼片段如下:
OpusEncoder *opus_enc = opus_encoder_create(16000,1,OPUS_APPLICATION_VOIP, &err);
…
opus_encoder_ctl(opus_enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_WIDEBAND));
opus_encoder_ctl(opus_enc, OPUS_SET_BITRATE(24000));
opus_encoder_ctl(opus_enc, OPUS_SET_VBR(1));
opus_encoder_ctl(opus_enc, OPUS_SET_FORCE_CHANNELS(1));
opus_encoder_ctl(opus_enc, OPUS_SET_DTX(0));
…
while (total_length - input_pos > frame_bytes) { //僅處理采集片段,而非長期占用線程
…
get_data(input_buf, input_pos);
num = opus_encode(opus_enc, input_buf, frame_size, output_buf, max_output_size);
send_data(output_buf, num);
… }
…
opus_encoder_destroy(opus_enc);
3.3 混音流程
多路語音的數(shù)據(jù)混音是語音集群通信的核心功能。通過混音算法和調(diào)平參數(shù),同一群組內(nèi)的多路通話語音將根據(jù)逐幀數(shù)據(jù)的時間戳進行合幀處理,形成一路語音數(shù)據(jù),送入聲卡緩沖區(qū)進行放音。不論語音數(shù)據(jù)是以8位、16位或浮點形式存儲,在多路混音時僅做邏輯疊加運算將會導致數(shù)據(jù)越界,必須先通過調(diào)平參數(shù)進行數(shù)據(jù)調(diào)整,之后根據(jù)疊加系數(shù)按比例縮減,保證合幀后的語音數(shù)據(jù)不會越界[11][12]。
混音操作的代碼片段如下:
mixlocker.lock();
…
foreach(audio_source as, mixlist) {
source_buf = as.getbuf();
level = volume_level * generate_adjust(); // 設置調(diào)平參數(shù)
…
for (unsigned int i = 0; i < sample_num; i++)
mix_buf[i] += source_buf[i] * level;
… }
…
for (unsigned int i = 0; i < sample_num; i++) // 數(shù)據(jù)越界保護
mix_buf[i] = bound(mix_buf[i], -32768, 32767);
…
mixlocker.lock();
4 實驗與分析
本系統(tǒng)分別在10M專線、聯(lián)通4G、移動4G、電信4G等網(wǎng)絡條件下進行測試,測試結果如表1所示。
在不同網(wǎng)絡環(huán)境下,語音數(shù)據(jù)傳輸?shù)钠骄訒r在可接受范圍,UDP丟包率小于2.2%,網(wǎng)絡抖動小于20ms。通過主觀測試,語音通話連貫,無連續(xù)丟幀,可懂性良好。因此,語音集群通信系統(tǒng)在傳輸延遲、網(wǎng)絡抖動等方面可以較好滿足語音集群和實時通信要求。在編碼處理方面,優(yōu)于國際電聯(lián)G.711語音編碼的90kbps帶寬占用。
5 結束語
本文主要根據(jù)移動網(wǎng)絡環(huán)境下的語音集群通信需求,給出一套可行的系統(tǒng)解決方案,并對其中底層鏈路、應用構建、核心編碼處理等關鍵環(huán)節(jié)進行詳細闡述。在實際應用過程中,不同領域的業(yè)務單位可能對系統(tǒng)的數(shù)據(jù)存儲、用戶負載、網(wǎng)絡安全有更高的業(yè)務需求,可以通過合理配置磁盤陣列、負載均衡、安全網(wǎng)關、服務器等硬件設備或軟件服務來實現(xiàn)。
參考文獻:
[1] 2015年中國移動語音社交應用行業(yè)研究報告[R]. 上海: iResearch, 2015:19-23
[2] 王芳. 數(shù)字集群通信系統(tǒng)的構成及功能[J]. 電信網(wǎng)技術, 2005(2):9-12.
[3] Chauncey D, Kuliner M. Secure wireless communications system and related method: WO, US7987363[P]. 2011.
[4] 曾強. 網(wǎng)絡安全協(xié)議SSL原理及應用[D]. 天津:天津大學, 2005.
[5] 秦貞虎. 基于OpenSSL開發(fā)的聊天工具的設計與實現(xiàn)[D]. 成都:電子科技大學, 2013.
[6] 李一鳴, 任勇毛, 李俊. 基于UDP的傳輸協(xié)議性能比較與分析[J]. 計算機應用研究, 2010, 27(10):3906-3910.
[7] 趙興. 基于VoIP技術的無線語音通信系統(tǒng)設計[D].長沙: 湖南大學, 2011.
[8] opus-codec. Quality vs Bitrate[EB/OL]. http:///comparison/.
[9] opus-codec. Google listening tests[EB/OL]. http:///comparison/GoogleTest1.pdf.
[10] opus-codec. Google listening tests[EB/OL]. http:///comparison/GoogleTest2.pdf.