新聞中心

        EEPW首頁 > 手機與無線通信 > 設計應用 > 對Windows TCP/IP協議棧的一種簡化設計

        對Windows TCP/IP協議棧的一種簡化設計

        作者: 時間:2012-05-22 來源:網絡 收藏

        2.2 設置多級優先級隊列

        在網絡數據傳輸中,由于有些緊急數據希望盡快發送出去提交給目的主機,而曰前的系統網絡傳輸機制并沒有提供這樣的功能。可以通過采用多級優先級隊列的方式來達到一定的實時效果,比如對于緊急數據,可以設置最高優先級值,而一般數據就可以設置最低優先級值。在用戶應用程序中,對發送函數進行封裝,新的發送函數有個優先級參數,通過指明優先級參數值靈活處理數據,當提交給內核時,就按照優先級值放到相對應的優先級隊列中。相應的在內核收包、發包緩沖區中,設置多級優先級隊列,按照多級反饋隊列調度算法進行處理,每個隊列的優先級不同,并且每個隊列的被處理的時間不同,各個隊列的時間片是隨著優先級的減少而增加的,優先級越高的隊列中它的被線程處理的時間也就越短。比如緊急數據放到最高優先級隊列中,遲緩的數據可以放到最低優先級隊列中,在內核的發包線程中,首先判斷最高優先級隊列是否為空,不為空則優先發送該隊列中的數據包,當該隊列的時間用完,如果該隊列還有包沒有處理完,則把這些包鏈接到低一級的隊列尾部,然后判斷低一級優先級隊列是否為空,重復以上的操作依次進行下去,當對最低優先級隊列處理完后,再循環處理。如果線程在處理第i隊列的數據時,這時候有新的用戶數據進入到比i隊列優先級高的j隊列中,則線程處理完該數據就立即去處理j隊列,這個可以用一個掩碼mask,每一位標識一個隊列,當隊列不為空,則該標識位置為1,否則置為0。

        2.3 封裝Socket層

        創建Socket套接字,就是打開設備對象(第一次是創建,之后就是打開),而打開設備對象就會創建一個內核文件對象,這個內核文件對象其實就可以映射創建的Socket套接字。對于打開設備對象,就可以用CreateFile()函數,并且把返回的句柄定義為Socekt句柄,之后的操作就可以直接用這個Socket句柄進行操作,如send()函數,可以用WriteFile()函數封裝實現;Receive()函數可以用ReadFile()函數封裝實現;bind()函數、setsockopt()函數、getsockopt()函數都可以通過DeviceIoControl()函數封裝實現。為了真正實現打開設備等操作,需要在驅動程序中塒各個用戶應用程序下達的IRP請求進行響應,用派遣函數就可以實現。在圖2中,用戶程序可以通過新封裝好的Socket層,使用原來同樣的Socket編程語句,這樣使用戶使用起來感覺沒有差別,對用戶是透明的。

        2.4 驅動

        在應用程序中,對同一個線程環境下的文件句柄的讀,寫等,映射到內核中的IRP I/O堆棧的內核文件對象File()bject是同一個File()bject,這樣可以用內核文件對象作為紐帶作用。在驅動的設備擴展NDISPROT_OPEN_CONTEXT結構體內,建立一個File Port鏈表,如圖3所示。鏈表的每個節點包含有內核文件對象、接收數據緩沖區、發送數據緩沖區、端口號、接收數據緩沖區大小、發送數據緩沖區大小等兒部分。內核文件對象用來標識是哪一個用戶Socket句柄;接收、發送數據緩沖區用來存放Socket的接收、發送的數據;端口號的作用是讓網絡數據包可以知道提交到哪個內核文件對象下的接收緩沖區;接收、發送數據緩沖區大小指明接收、發送緩沖區最大的長度。如果緩沖區隊列滿,而這時候又有數據過來,則該數據應被丟棄。在協議驅動程序里面,利用這個FilePort鏈表,可以實現收發數據,設置接收、發送緩沖區的大小等操作。

        需要注意的是在NDISPROT_OPEN_CONTEXT結構體內,需創建一個NPROT_LOCK類型的鎖,用來對FilePort鏈表進行互斥訪問。

        2.4.1 端口號的綁定

        在協議驅動設備擴展中需要建立一張表,里面存放已默認分配的端口號以及用戶綁定的端口號,端口號是從小到大按序排列,表的作用是當用戶應用程序綁定端口號操作時,首先會通過二叉查找法查找這張表,看該端口號是否存放在該表中,如果找到,則要返回給應用程序綁定失敗,如果沒有找到,則把該端口號插入到適當位置,并返回給應用程序綁定成功。用戶應用程序通過調用bind()函數實現綁定Socket套接字,其含義就是用端口號來惟一標識用戶線程下的Socket,讓網絡數據包提交給正確的Socket,在bind函數里面可以通過封裝DeviceIo Control函數調用來實現。

        2.4.2 發送數據過程

        用戶應用程序發送的IRP寫請求(WriteFile()函數),傳遞到協議驅動程序后,調用派遣函數NdisProtWrite,通過IRP I/O堆棧里面的內核文件對象循環遍歷FilePort鏈表找到對應的節點,然后把用戶應用程序的數據通過緩沖區讀寫設備的方式拷貝到NDISPROT_OPEN_CONTEXT結構的相應的Priority SendQueue優先級隊列中。如圖3所示,發包線程的工作主要有,從Priority SendQueue優先級隊列中提取數據,如何提取按照多級反饋隊列調度算法處理,經過協議棧,然后再調用NdisSendPackets函數發送給網卡驅動程序。在協議棧中,把該數據的優先級值賦值給首部的服務類型(TOS)字段中,使收包的時候根據此字段的優先級值把包放進相應的收包優先級隊列中。

        2.4.3 接收數據過程

        協議驅動從網卡驅動程序接收網絡數據包,這些數據包是打包封裝好的,首先存放在NDISPROT_OPEN_CONTEXT結構的收包優先級隊列Pri ority RecvQueue中,這樣可以接收到高速上傳過來的底層數據。如圖3所示,需要建立一個收包處理線程,它的主要工作是,從收包優先級隊列提取數據,具體算法根據上面的多級反饋隊列調度算法,然后經由/IP協議棧的處理,如果是UDP,TCP的數據包則通過包的目的端口號,遍歷FilePort鏈表找到對應的節點,然后把剩下的凈數據提交給節點(目標Socket)的收包緩沖區中。值得注意的是,因為NDIS封裝數據用的是NDIS_PACKET結構,NDIS_PACKET結構里面包含一個NDIS_BUFFER結構的鏈表,在每個NDIS_BUFFER里面才真正指向數據的首地址,這里說的提交,并沒有拷貝數據,只是把凈數據的首地址再次鏈接到FilePort鏈表中。當用戶應用程序通過Receive()函數接收數據的時候,會調用ReadFile()函數,發出讀IRP請求,IRP到達協議驅動后,調用NdisProtRead()派遣函數處理,NdisProtRead()會通過IRP I/O堆棧里面的內核文件對象,遍歷FilePort鏈表,找到相應的節點,再把節點接收緩沖區里面的數據拷貝到用戶緩沖區里面。

        c.JPG

        tcp/ip相關文章:tcp/ip是什么




        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 美姑县| 大同县| 同心县| 甘洛县| 昆山市| 新宁县| 田东县| 古浪县| 介休市| 中宁县| 南部县| 河南省| 寿阳县| 长顺县| 淮滨县| 怀来县| 革吉县| 兰考县| 大宁县| 封开县| 宁安市| 揭西县| 柏乡县| 宣恩县| 靖远县| 临安市| 迭部县| 灵寿县| 庆元县| 方城县| 北流市| 祁连县| 乐都县| 新平| 洛浦县| 奇台县| 东兰县| 于都县| 乌审旗| 高雄市| 万源市|