天又有人向我推薦某個庫,據說能比winsock好使,增加了各種各樣的新特性
於是我打算說說這個事情,因為實在太多了
其實之所以出現那麼多的winsock擴充,只是因為微軟先有了那個破win95,
導致了winsock也成了一個非常非常蹩腳的封裝,又因為這個蹩腳的winsock,才會有這許多的擴充舉個例子,就說connect
connect是一個bsd的東西,它是非非同步操作,在windows上線程的代價昂貴,所以很多人都頭疼這個東西
微軟明顯也知道這個問題,所以它有自己的一個擴充,就是WSAConnect,這個玩意兒可以讓你指定一個事件,
然後你可以在connect完成之後得到一個事件的signal
然後這個還是不夠,又在XP/2003裡面加上一個ConnectEx,這就可以不局限於事件了,可以用APC,還能綁定到IOCP.現在許多所謂的擴充,很大程度上不外乎是或者利用了這些新的函數,或者自己做一套來解決相似的問題
可是其實這全都不是什麼新東西,早在NT 4.0就已經有了
一個SOCKET無非是一個控制代碼,它具有IFS 控制代碼的所有特性,本來就是非同步,本來就可以綁定到IOCP上,就說這個connect,
經過了winsock封裝的層層中轉之後,它最終不外是達到這樣一個調用status = NtDeviceIoControlFile(
Socket,
NULL,
NULL,
ConnectContext,
&ConnectContext->IoStatusBlock,
IOCTL_AFD_CONNECT,
&ConnectContext->ConnectInfo,
ConnectContext->ConnectInfoLength,
&ConnectContext->IoStatusBlock,
sizeof (ConnectContext->IoStatusBlock)
);這裡第一個NULL本來可以是一個事件的控制代碼,第二個NULL本來可以是一個APC函數的地址,通過這兩個參數,你本可以
1.設定一個事件,connect完成後得到一個signal
2.設定一個APC函數,
a) connect完成之後得到一個callback,在調用線程執行
b) connect完成之後得到一個callback,在socket綁定的IOCP線程執行只是winsock沒有讓你設定這兩個參數,而是簡單的把它們設為NULL,結果把這個功能隱藏起來了 ! (現在卻裝作給了你兩個新函數)
微軟就是這樣奇怪,他做了一個完整的核心,然後通過一個蹩腳的封裝,給你一個破產品...相似的例子就是那個破OVERLAPPED結構,在NT核心當中,所有的callback context都是一個void *,這本來可以有更好的C++相容性
不知道微軟那些人怎麼想的,弄出OVERLAPPED這麼個畸形的玩意兒,結果呢?本來你可以這樣做(NTDLL)
struct TWorker
{
virtual void __stdcall OnCompletion(IO_STATUS_BLOCK * Status)
{
// File Read Completed, process data
}
}
TWorker * pWorker = new Tworker;
NtReadFile( hFile,pWorker....) 通過OVERLAPPED結構卻不能,因為在ReadFile中只能指定一個OVERLAPPED的指標,TWorker卻不能繼承OVERLAPPED結構,因為沒有地方放VTBL !結果只能變成(KERNEL32)struct MY_OVERLAPPED : OVERLAPPED
{
TWorker * m_pWorker;
};
ReadFile(hFile,.... MY_OVERLAPPED *)....彆扭吧? 鬱悶吧? 因為這個醜陋的OVERLAPPED結構,原來非常簡潔的iocp,一個典型的client/server方式,變成了雜亂的GetOverlappedResult那樣的垃圾... 其實這些東西在微軟也已經亂了套,就說ConnectEx吧,執行完畢,你如果調用WSAGetLastError,返回的是一個Winsock 的錯誤碼,但如果你把它綁定到一個完成連接埠,返回的卻是一個標準的NTSATUS ! 這兩者的區別就不用我說了吧...