用Winsock實現(xiàn)語音全雙工通信

字號:

一、引言
     Windows 95作為微機的操作系統(tǒng),已經(jīng)完全融入了網(wǎng)絡(luò)與通信功能,不僅可以建立純Windows 95環(huán)境下的“對等網(wǎng)絡(luò)”,而且支持多種協(xié)議,如TCP/IP、IPX/SPX、NETBUI等。在TCP/IP協(xié)議組中,TPC是一種面向連接的協(xié)義,為用戶提供可靠的、全雙工的字節(jié)流服務(wù),具有確認、流控制、多路復(fù)用和同步等功能,適于數(shù)據(jù)傳輸。UDP協(xié)議則是無連接的,每個分組都攜帶完整的目的地址,各分組在系統(tǒng)中獨立傳送。它不能保證分組的先后順序,不進行分組出錯的恢復(fù)與重傳,因此不保證傳輸?shù)目煽啃?,但是,它提供高傳輸效率的?shù)據(jù)報服務(wù),適于實時的語音、圖像傳輸、廣播消息等網(wǎng)絡(luò)傳輸。
     Winsock接口為進程間通信提供了一種新的手段,它不但能用于同一機器中的進程之間通信,而且支持網(wǎng)絡(luò)通信功能。隨著Windows 95的推出。Winsock已經(jīng)被正式集成到了Windows系統(tǒng)中,同時包括了16位和32位的編程接口。而Winsock的開發(fā)工具也可以在Borland C++4.0、Visual C++2.0這些C編譯器中找到,主要由一個名為winsock.h的頭文件和動態(tài)連接庫winsock.dll或wsodk32.dll組成,這兩種動態(tài)連接庫分別用于Win16和Win32的應(yīng)用程序。
    本文針對話音的全雙工傳輸要求,采用UDP協(xié)議實現(xiàn)了實時網(wǎng)絡(luò)通信。使用VisualC++2.0編譯環(huán)境,其動態(tài)連接庫名為wsock32.dll。
    二、主要函數(shù)的使用要點
    通過建立雙套接字,可以很方便地實現(xiàn)全雙工網(wǎng)絡(luò)通信。
    1.套接字建立函數(shù):
    SOCKET socket(int family,int type,int protocol)
    對于UDP協(xié)議,寫為:
    SOCKRET s;
    s=socket(AF_INET,SOCK_DGRAM,0);
    或s=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)
    為了建立兩個套接字,必須實現(xiàn)地址的重復(fù)綁定,即,當(dāng)一個套接字已經(jīng)綁定到某本地地址后,為了讓另一個套接字重復(fù)使用該地址,必須為調(diào)用bind()函數(shù)綁定第二個套接字之前,通過函數(shù)setsockopt()為該套接字設(shè)置SO_REUSEADDR套接字選項。通過函數(shù)getsockopt()可獲得套接字選項設(shè)置狀態(tài)。需要注意的是,兩個套接字所對應(yīng)的端口號不能相同。
    此外,還涉及到套接字緩沖區(qū)的設(shè)置問題,按規(guī)定,每個區(qū)的設(shè)置范圍是:不小于512個字節(jié),大大于8k字節(jié),根據(jù)需要,文中選用了4k字節(jié)。
    2.套接字綁定函數(shù)
    int bind(SOCKET s,struct sockaddr_in*name,int namelen)
    s是剛才創(chuàng)建好的套接字,name指向描述通訊對象的結(jié)構(gòu)體的指針,namelen是該結(jié)構(gòu)體的長度。該結(jié)構(gòu)體中的分量包括:IP地址(對應(yīng)name.sin_addr.s_addr)、端口號(name.sin_port)、地址類型(name.sin_family,一般都賦成AF_INET,表示是internet地址)。
     (1)IP地址的填寫方法:在全雙工通信中,要把用戶名對應(yīng)的點分表示法地址轉(zhuǎn)換成32位長整數(shù)格式的IP地址,使用inet_addr()函數(shù)。
    (2)端口號是用于表示同一臺計算機不同的進程(應(yīng)用程序),其分配方法有兩種:1)進程可以讓系統(tǒng)為套接字自動分配一端口號,只要在調(diào)用bind前將端口號指定為0即可。由系統(tǒng)自動分配的端口號位于1024~5000之間,而1~1023之間的任一TCP或UDP端口都是保留的,系統(tǒng)不允許任一進程使用保留端口,除非其有效用戶ID是零(超級用戶)。
     (2)進程可為套接字指定一特定端口。這對于需要給套接字分配一眾所端口的服務(wù)器是很有用的。指定范圍為1024和65536之間∩任意指定。
    在本程序中,對兩個套接字的端口號規(guī)定為2000和2001,前者對應(yīng)發(fā)送套接字,后者對應(yīng)接收套接字。
    端口號要從一個16位無符號數(shù)(u_short類型數(shù))從主機字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序,使用
    htons()函數(shù)。
    根據(jù)以上兩個函數(shù),可以給出雙套接字建立與綁定的程序片斷;
    //設(shè)置有關(guān)的全局變量
    SOCKET sr,ss;
    HPSTR sockBufferS,sockBufferR;
    HANDLE hSendData,hReceiveData;
    DWROD dwDataSize=1024*4;
    struct sockaddr_in therel.there2;
    #DEFINE LOCAL_HOST_ADDR 200.200.200.201
    #DEFINE REMOTE_HOST-ADDR 200.200.200.202
    #DEFINE LOCAL_HOST_PORT 2000
    #DEFINE LOCAL_HOST_PORT 2001
    //套接字建立函數(shù)