| 方案 | 核心思路 | 優點 | 缺點 | 適合場景 |
|---|---|---|---|---|
| 1. MFC 直接嵌入 | 將 Socket 代碼移植到 MFC 對話框/文檔視圖類中,消息泵驅動收發 | 純 C++、無跨語言邊界、原生性能、VS 資源編輯器拖拽 UI | UI 開發效率低、界面風格舊、高 DPI 支持弱 | 團隊只懂 C++、需極致性能、維護舊 MFC 專案 |
| 2. C++/CLI 混合模式 | 編譯選項 `/clr`,C++ 代碼直接調用 .NET WinForms/WPF,托管/非托管互調 | 現有 C++ 幾乎不改、可用現代 .NET UI、同一進程零拷貝傳遞數據 | 語法怪異(`gcnew` `^` `%`)、調試困難、VS 新版本支持下降、部署需 .NET Runtime | 快速遷移、需調用 .NET 庫、過渡方案 |
| 3. C# 重寫 / 互操作(推薦) | 核心邏輯封裝為 C++ DLL(導出 C 接口),C# P/Invoke 調用;或直接用 C# 重寫 Socket | C# 生態豐富、UI 開發極快(WinForms/WPF/MAUI/Avalonia)、跨平台潛力、招人易 | 需定義清晰邊界、封送開銷、雙語言維護成本 | 長期項目、團隊有 C# 能力、追求現代 UI/跨平台 |
// SocketCore.h
#ifdef SOCKETCORE_EXPORTS
#define SOCKETCORE_API __declspec(dllexport)
#else
#define SOCKETCORE_API __declspec(dllimport)
#endif
extern "C" {
SOCKETCORE_API int StartServer(unsigned short port, void (*onRecv)(const char*, int));
SOCKETCORE_API int ConnectServer(const char* ip, unsigned short port);
SOCKETCORE_API int SendData(const char* data, int len);
SOCKETCORE_API void StopServer();
SOCKETCORE_API void Disconnect();
}
public static class NativeSocket
{
[DllImport("SocketCore.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int StartServer(ushort port, RecvCallback callback);
[DllImport("SocketCore.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ConnectServer(string ip, ushort port);
[DllImport("SocketCore.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int SendData(byte[] data, int len);
[DllImport("SocketCore.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void StopServer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void RecvCallback(byte[] data, int len);
}
public partial class MainForm : Form
{
private NativeSocket.RecvCallback _recvCb;
public MainForm()
{
InitializeComponent();
_recvCb = OnDataReceived; // 防止委托被 GC
}
private void btnStart_Click(object sender, EventArgs e)
{
int ret = NativeSocket.StartServer(55321, _recvCb);
if (ret == 0) txtLog.AppendText("Server started\n");
}
private void OnDataReceived(byte[] data, int len)
{
string msg = Encoding.UTF8.GetString(data, 0, len);
// 跨線程更新 UI
Invoke(() => txtLog.AppendText($"Recv: {msg}\n"));
}
}
若極度趕工、不想拆 DLL:
**長期看:C# 重寫或 C++ DLL + C# P/Invoke 最划算**,UI 開發效率碾壓 MFC,生態現代,招人容易。**短期救急:C++/CLI (/clr) 能最快跑通**,但屬技術債,規劃遷移。純 MFC 只適合純 C++ 團隊且無跨平台需求的維護型專案。