引入Winsock与ws2_32库后VS编译持续失败的原因及解决方法
问题定位与解决方案
核心问题分析
编译时的结构体、宏重定义错误,根源是Winsock1与Winsock2头文件冲突:windows.h会自动引入旧版winsock.h,后续再包含winsock2.h就会导致重复定义sockaddr等结构体、AF_IPX等宏。
具体修复步骤
1. 调整头文件包含逻辑
修改UDPSocketComm.h,确保先引入Winsock2再引入Windows头文件,同时清理冗余内容:
// UDPSocketComm.h #ifndef _UDP_SOCKET_COMM_H_ #define _UDP_SOCKET_COMM_H_ // 先包含Winsock2,避免windows.h引入旧版winsock.h #include <winsock2.h> #include <windows.h> #include <string> class UDPSocketComm { private : SOCKET receiverSocket; std::string serverAddr; uint32_t receiverPort; struct sockaddr_in receiver; public: int OpenSocket(const char* serverAddr, uint32_t portNum); int SendData(const char* data, unsigned long length); int EndConnection(); }; #endif
- 移除
#pragma comment(lib, "ws2_32.lib"):CMake已配置链接库,无需重复声明 - 移除
WS2tcpip.h:winsock2.h已包含基础UDP通信所需定义,若需新API可保留,但要保证包含顺序在windows.h之前
2. 清理CMake冗余链接
同时链接ws2_32和wsock32会引发新旧库冲突,只保留Winsock2的库即可:
target_link_libraries(MyDll PUBLIC ws2_32)
3. 补充缺失的函数实现
头文件声明了SendData但未实现,需在UDPSocketComm.cpp中补充:
int UDPSocketComm::SendData(const char* data, unsigned long length) { int sendResult = sendto(receiverSocket, data, length, 0, (SOCKADDR*)&receiver, sizeof(receiver)); return sendResult == SOCKET_ERROR ? WSAGetLastError() : sendResult; }
4. 优化包装类代码
确保导出函数完全被extern "C"包裹,避免C++名称修饰问题:
// MyDLL.cpp #include "UDPSocketComm.h" UDPSocketComm comObj; extern "C" { __declspec(dllexport) int Init(const char* server, uint32_t port) { return comObj.OpenSocket(server, port); } __declspec(dllexport) int Terminate() { return comObj.EndConnection(); } __declspec(dllexport) int Send(const char* data, unsigned long length) { return comObj.SendData(data, length); } }
额外注意事项
WSAStartup和WSACleanup需保证全局只调用一次:当前代码每次调用OpenSocket都会执行WSAStartup,多次调用会报错,建议将WSAStartup放在类构造函数或全局初始化逻辑中,WSACleanup放在析构函数中。- 若DLL仅需发送数据,无需调用
bind:bind是绑定本地端口用于接收,纯发送场景直接调用sendto即可。
内容的提问来源于stack exchange,提问作者doa4321
相关产品推荐
相关产品推荐

