• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            道。道。道

            安全特性不等于安全的特性

               :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理

            常用鏈接

            搜索

            •  

            最新評論

              摘要:在Windows 95環(huán)境下,基于TCP/IP協(xié)議,用Winsock完成了話音的端到端傳輸。采用雙套接字技術(shù),闡述了主要函數(shù)的使用要點,以及基于異步選擇機制的應(yīng)用方法。同時,給出了相應(yīng)的實例程序。

              一、引言

              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ù),具有確認(rèn)、流控制、多路復(fù)用和同步等功能,適于數(shù)據(jù)傳輸。UDP協(xié)議則是無連接的,每個分組都攜帶完整的目的地址,各分組在系統(tǒng)中獨立傳送。它不能保證分組的先后順序,不進(jìn)行分組出錯的恢復(fù)與重傳,因此不保證傳輸?shù)目煽啃裕牵峁└邆鬏斝实臄?shù)據(jù)報服務(wù),適于實時的語音、圖像傳輸、廣播消息等網(wǎng)絡(luò)傳輸。

              Winsock接口為進(jìn)程間通信提供了一種新的手段,它不但能用于同一機器中的進(jìn)程之間通信,而且支持網(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)端口號是用于表示同一臺計算機不同的進(jìn)程(應(yīng)用程序),其分配方法有兩種:1)進(jìn)程可以讓系統(tǒng)為套接字自動分配一端口號,只要在調(diào)用bind前將端口號指定為0即可。由系統(tǒng)自動分配的端口號位于1024~5000之間,而1~1023之間的任一TCP或UDP端口都是保留的,系統(tǒng)不允許任一進(jìn)程使用保留端口,除非其有效用戶ID是零(超級用戶)。

              2)進(jìn)程可為套接字指定一特定端口。這對于需要給套接字分配一眾所端口的服務(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ù)
            BOOL make_skt(HWND hwnd)
            {
            struct sockaddr_in here,here1;
            ss=socket(AF_INET,SOCK_DGRAM,0);
            sr=socket(AF_INET,SOCK_DGRAM,0);
            if((ss==INVALID_SOCKET)||(sr==INVALID_SOCKET))
            {
            MessageBox(hwnd,“套接字建立失敗!”,“”,MB_OK);
            return(FALSE);
            }
            here.sin_family=AF_INET;
            here.sin_addr.s_addr=inet_addr(LOCAL_HOST_ADDR);
            here.sin_port=htons(LICAL_HOST_PORT);
            //another socket
            herel.sin_family=AF_INET;
            herel.sin_addr.s_addr(LOCAL_HOST_ADDR);
            herel.sin_port=htons(LOCAL_HOST_PORT1);
            SocketBuffer();//套接字緩沖區(qū)的鎖定設(shè)置
            setsockopt(ss,SOL_SOCKET,SO_SNDBUF,(char FAR*)sockBufferS,dwDataSize);
            if(bind(ss,(LPSOCKADDR)&here,sizeof(here)))
            {
            MessageBox(hwnd,“發(fā)送套接字綁定失敗!”,“”,MB_OK);
            return(FALSE);
            }
            setsockopt(sr SQL_SOCKET,SO_RCVBUF|SO_REUSEADDR,(char FAR*)
            sockBufferR,dwDataSize);
            if(bind(sr,(LPSOCKADDR)&here1,sizeof(here1)))
            {
            MessageBox(hwnd,“接收套接字綁定失敗!”,“”,MB_OK);
            return(FALSE);
            }
            return(TRUE);
            }
            //套接字緩沖區(qū)設(shè)置
            void sockBuffer(void)
            {
            hSendData=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,dwDataSize);
            if(!hSendData)
            {
            MessageBox(hwnd,“發(fā)送套接字緩沖區(qū)定位失敗!”,NULL,
            MB_OK|MB_ICONEXCLAMATION);
            return;
            }
            if((sockBufferS=GlobalLock(hSendData)==NULL)
            {
            MessageBox(hwnd,“發(fā)送套接字緩沖區(qū)鎖定失敗!”,NULL,
            MB_OK|MB_ICONEXCLAMATION);
            GlobalFree(hRecordData[0];
            return;
            }
            hReceiveData=globalAlloc(GMEM_MOVEABLE|GMEM_SHARE,dwDataSize);
            if(!hReceiveData)
            {
            MessageBox(hwnd,"“接收套接字緩沖區(qū)定位敗!”,NULL
            MB_OK|MB_ICONEXCLAMATION);
            return;
            }
            if((sockBufferT=Globallock(hReceiveData))=NULL)
            MessageBox(hwnd,"發(fā)送套接字緩沖區(qū)鎖定失敗!”,NULL,
            MB_OK|MB_ICONEXCLAMATION);
            GlobalFree(hRecordData[0]);
            return;
            }
            {

              3.數(shù)據(jù)發(fā)送與接收函數(shù);

            int sendto(SOCKET s.char*buf,int len,int flags,struct sockaddr_in to,int
            tolen);
            int recvfrom(SOCKET s.char*buf,int len,int flags,struct sockaddr_in
            fron,int*fromlen)

              其中,參數(shù)flags一般取0。

              recvfrom()函數(shù)實際上是讀取sendto()函數(shù)發(fā)過來的一個數(shù)據(jù)包,當(dāng)讀到的數(shù)據(jù)字節(jié)少于規(guī)定接收的數(shù)目時,就把數(shù)據(jù)全部接收,并返回實際接收到的字節(jié)數(shù);當(dāng)讀到的數(shù)據(jù)多于規(guī)定值時,在數(shù)據(jù)報文方式下,多余的數(shù)據(jù)將被丟棄。而在流方式下,剩余的數(shù)據(jù)由下recvfrom()讀出。為了發(fā)送和接收數(shù)據(jù),必須建立數(shù)據(jù)發(fā)送緩沖區(qū)和數(shù)據(jù)接收緩沖區(qū)。規(guī)定:IP層的一個數(shù)據(jù)報最大不超過64K(含數(shù)據(jù)報頭)。當(dāng)緩沖區(qū)設(shè)置得過多、過大時,常因內(nèi)存不夠而導(dǎo)致套接字建立失敗。在減小緩沖區(qū)后,該錯誤消失。經(jīng)過實驗,文中選用了4K字節(jié)。

              此外,還應(yīng)注意這兩個函數(shù)中最后參數(shù)的寫法,給sendto()的最后參數(shù)是一個整數(shù)值,而recvfrom()的則是指向一整數(shù)值的指針。

              4.套接字關(guān)閉函數(shù):closesocket(SOCKET s)

              通訊結(jié)束時,應(yīng)關(guān)閉指定的套接字,以釋與之相關(guān)的資源。

              在關(guān)閉套接字時,應(yīng)先對鎖定的各種緩沖區(qū)加以釋放。其程序片斷為:

            void CloseSocket(void)
            {
            GlobalUnlock(hSendData);
            GlobalFree(hSenddata);
            GlobalUnlock(hReceiveData);
            GlobalFree(hReceiveDava);
            if(WSAAysncSelect(ss,hwnd,0,0)=SOCKET_ERROR)
            {
            MessageBos(hwnd,“發(fā)送套接字關(guān)閉失敗!”,“”,MB_OK);
            return;
            }
            if(WSAAysncSelect(sr,hwnd,0,0)==SOCKET_ERROR)
            {
            MessageBox(hwnd,“接收套接字關(guān)閉失敗!”,“”,MB_OK);
            return;
            }
            WSACleanup();
            closesockent(ss);
            closesockent(sr);
            return;
            }

              三、Winsock的編程特點與異步選擇機制

              1 阻塞及其處理方式

              在網(wǎng)絡(luò)通訊中,由于網(wǎng)絡(luò)擁擠或一次發(fā)送的數(shù)據(jù)量過大等原因,經(jīng)常會發(fā)生交換的數(shù)據(jù)在短時間內(nèi)不能傳送完,收發(fā)數(shù)據(jù)的函數(shù)因此不能返回,這種現(xiàn)象叫做阻塞。Winsock對有可能阻塞的函數(shù)提供了兩種處理方式:阻塞和非阻塞方式。在阻塞方式下,收發(fā)數(shù)據(jù)的函數(shù)在被調(diào)用后一直要到傳送完畢或者出錯才能返回。在阻塞期間,被阻的函數(shù)不會斷調(diào)用系統(tǒng)函數(shù)GetMessage()來保持消息循環(huán)的正常進(jìn)行。對于非阻塞方式,函數(shù)被調(diào)用后立即返回,當(dāng)傳送完成后由Winsock給程序發(fā)一個事先約定好的消息。

              在編程時,應(yīng)盡量使用非阻塞方式。因為在阻塞方式下,用戶可能會長時間的等待過程中試圖關(guān)閉程序,因為消息循環(huán)還在起作用,所以程序的窗口可能被關(guān)閉,這樣當(dāng)函數(shù)從Winsock的動態(tài)連接庫中返回時,主程序已經(jīng)從內(nèi)存中刪除,這顯然是極其危險的。

              2 異步選擇函數(shù)WSAAsyncSelect()的使用

              Winsock通過WSAAsyncSelect()自動地設(shè)置套接字處于非阻塞方式。使用WindowsSockets實現(xiàn)Windows網(wǎng)絡(luò)程序設(shè)計的關(guān)鍵就是它提供了對網(wǎng)絡(luò)事件基于消息的異步存取,用于注冊應(yīng)用程序感興趣的網(wǎng)絡(luò)事件。它請求Windows Sockets DLL在檢測到套接字上發(fā)生的網(wǎng)絡(luò)事件時,向窗口發(fā)送一個消息。對UDP協(xié)議,這些網(wǎng)絡(luò)事件主要為:

              FD_READ 期望在套接字收到數(shù)據(jù)(即讀準(zhǔn)備好)時接收通知;

              FD_WRITE 期望在套接字可發(fā)送數(shù)(即寫準(zhǔn)備好)時接收通知;

              FD_CLOSE 期望在套接字關(guān)閉時接電通知

              消息變量wParam指示發(fā)生網(wǎng)絡(luò)事件的套接字,變量1Param的低字節(jié)描述發(fā)生的網(wǎng)絡(luò)事件,高字包含錯誤碼。如在窗口函數(shù)的消息循環(huán)中均加一個分支:

            int ok=sizeof(SOCKADDR);
            case wMsg;
            switch(1Param)
            {
            case FD_READ:
            //套接字上讀數(shù)據(jù)
            if(recvfrom(sr.lpPlayData[j],dwDataSize,0,(struct sockaddr FAR*)&there1,

            (int FAR*)&ok)==SOCKET_ERROR0
            {
            MessageBox)hwnd,“數(shù)據(jù)接收失敗!”,“”,MB_OK);
            return(FALSE);
            }
            case FD_WRITE:
            //套接字上寫數(shù)據(jù)
            }
            break;

              在程序的編制中,應(yīng)根據(jù)需要靈活地將WSAAsyncSelect()函靈敏放在相應(yīng)的消息循環(huán)之中,其它說明可參見文獻(xiàn)[1]。此外,應(yīng)該指出的是,以上程序片斷中的消息框主要是為程序調(diào)試方便而設(shè)置的,而在正式產(chǎn)品中不再出現(xiàn)。同時,按照程序容錯誤設(shè)計,應(yīng)建立一個專門的容錯處理函數(shù)。程序中可能出現(xiàn)的各種錯誤都將由該函數(shù)進(jìn)行處理,依據(jù)錯誤的危害程度不同,建立幾種不同的處理措施。這樣,才能保證雙方通話的順利和可靠。

              四、結(jié)論

              本文是多媒體網(wǎng)絡(luò)傳輸項目的重要內(nèi)容之一,目前,結(jié)合硬件全雙工語音卡等設(shè)備,已經(jīng)成功地實現(xiàn)了話音的全雙工的通信。有關(guān)整個多媒體傳輸系統(tǒng)設(shè)計的內(nèi)容,將有另文敘述。

            posted on 2007-01-31 11:47 獨孤九劍 閱讀(883) 評論(0)  編輯 收藏 引用 所屬分類: network protocol
            国产一区二区精品久久| 久久av免费天堂小草播放| 中文字幕人妻色偷偷久久| 无码专区久久综合久中文字幕 | 久久天天躁狠狠躁夜夜不卡| 香蕉久久夜色精品国产2020 | 一本色道久久综合| 久久成人国产精品| 色天使久久综合网天天 | 国产精品免费看久久久香蕉 | 99精品久久久久久久婷婷| 久久精品极品盛宴观看| 久久国产精品成人影院| 热综合一本伊人久久精品| 久久精品国产亚洲AV高清热| 久久九九免费高清视频| 久久亚洲日韩精品一区二区三区| 久久久久国产精品| 香蕉久久夜色精品升级完成| 久久精品国产亚洲AV不卡| 国产午夜精品理论片久久影视| 香蕉久久久久久狠狠色| 精品久久久久久久久久中文字幕| 久久久免费精品re6| 精品国产乱码久久久久久呢| 久久精品亚洲男人的天堂| 91精品国产综合久久久久久| 亚洲中文字幕无码久久精品1 | 亚洲精品高清久久| 精品国产乱码久久久久久1区2区| 亚洲午夜无码AV毛片久久| 欧美日韩精品久久久久| 久久久久一级精品亚洲国产成人综合AV区| 99久久中文字幕| 精品久久久久久综合日本| 久久久精品人妻一区二区三区四| 99久久精品免费看国产一区二区三区 | 曰曰摸天天摸人人看久久久| 91视频国产91久久久| 久久久久久久99精品免费观看| 成人久久精品一区二区三区|