首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 使用 Winsock API 實作同步 Socket 伺服器:P/Invoke 封裝 ws2_32.dll 核心函數

     編輯:關於C語言

大多講解 Winsock 的代碼都是 C++,而 Winsock 只是 Windows API 的使用,為了幫助 .NET 程式設計師深入理解 Winsock2,我把 .NET 下同步 Socket 的實作代碼拆出來並簡化,有空可自行除錯觀察。

注意事項

  • 僅能在 Windows 2000 以上系統運行
  • 僅支援 TCP 協定
  • 僅支援 IPv4

修改處

  1. 移除計數器、日誌等邏輯
  2. 不支援非同步、完成埠模型,待有時間再拆分完成埠部分

為免貼文過短,貼上代碼中用到的 Winsock 函數原型,想開發高效能網路程式,必須深入理解這幾個函數,可參考《Windows網路程式設計》第 7、8、9 章。

#region OSSOCK
[SuppressUnmanagedCodeSecurity]
internal static class OSSOCK
{
    [DllImport("ws2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
    internal static extern SocketError WSAStartup([In] short wVersionRequested, out WSAData lpWSAData);
    [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern SafeCloseSocket.InnerSafeCloseSocket WSASocket([In] AddressFamily addressFamily, [In] SocketType socketType, [In] ProtocolType protocolType, [In] IntPtr protocolInfo, [In] uint group, [In] SocketConstructorFlags flags);
    [DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern unsafe SafeCloseSocket.InnerSafeCloseSocket WSASocket([In] AddressFamily addressFamily, [In] SocketType socketType, [In] ProtocolType protocolType, [In] byte* pinnedBuffer, [In] uint group, [In] SocketConstructorFlags flags);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern SocketError bind([In] SafeCloseSocket socketHandle, [In] byte[] socketAddress, [In] int socketAddressSize);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern SocketError listen([In] SafeCloseSocket socketHandle, [In] int backlog);
    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern SocketError ioctlsocket([In] SafeCloseSocket socketHandle, [In] int cmd, [In, Out] ref int argp);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern unsafe int recv([In] IntPtr socketHandle, [In] byte* pinnedBuffer, [In] int len, [In] SocketFlags socketFlags);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern unsafe int send([In] IntPtr socketHandle, [In] byte* pinnedBuffer, [In] int len, [In] SocketFlags socketFlags);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern SocketError shutdown([In] SafeCloseSocket socketHandle, [In] int how);
    [DllImport("ws2_32.dll", SetLastError = true)]
    internal static extern SocketError setsockopt([In] SafeCloseSocket socketHandle, [In] SocketOptionLevel optionLevel, [In] SocketOptionName optionName, [In] ref int optionValue, [In] int optionLength);
}
#endregion

研究幾天 .NET Socket 對 IOCP 的封裝,發現確實複雜,不打算繼續拆代碼,改用平台調用自行撰寫 IOCP 範例。不管 .NET 如何發展(Remoting、WCF 等),底層仍是這幾個有限函數。真心建議大家好好研讀,日後網路程式出問題抓 dump、看呼叫堆疊就能知道阻塞在哪個 API、為何阻塞。學 WinDbg 只是那幾個指令,關鍵還得了解 CLR 內部運作機制、Win32 API、CRT、IL 甚至組合語言。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved