使用winsock2.h可能出现的两种编译错误

QT里的windows.h和winsock2.h重定义错误 windows.h和winsock2.h的相爱相杀的故事,在网络上广为流传,引发无数血案。各种作案场景,前置环境复杂纷繁,其中root原因和发生规律,以及解决方法,大致几种。今天就写上网上没有出现过的解决方法。 现场 前2天,一同事QT-Creator(msvc编译工具)开发一个远程socket通讯软件,包含 winsock2.h后,编译失败,各种重复winsock2.h里的结构体变量的重复包... 阅读详情

在我初学Windows网络编程时,曾经遇到过两类编译错误(VC6的Build窗口哗哗的显示了102个Errors),都是些类型未定义或者重复定义问题,让我感到很郁闷。这两种错误情况下的第一条错误信息分别为:

错误情形1:mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier
错误情形2:winsock2.h(99) : error C2011: 'fd_set' : 'struct' type redefinition

后来,我静下心来仔细分析一下错误提示及相关文件,终于找到了原因。

我们知道,Windows网络编程至少需要两个头文件:winsock2.h和windows.h,而在WinSock2.0之前还存在一个老版本的winsock.h。正是这三个头文件的包含顺序,导致了上述问题的出现。

先让我们看看winsock2.h的内容,在文件开头有如下宏定义:

#ifndef _WINSOCK2API_
#define _WINSOCK2API_
#define _WINSOCKAPI_   /* Prevent inclusion of winsock.h in windows.h */

_WINSOCK2API_很容易理解,这是最常见的防止头文件重复包含的保护措施。_WINSOCKAPI_的定义则是为了阻止对老文件winsock.h的包含,即是说,如果用户先包含了winsock2.h就不允许再包含winsock.h了,否则会导致类型重复定义。这是怎样做到的呢?很简单,因为winsock.h的头部同样存在如下的保护措施:

#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_

再回过头来看winsock2.h,在上述内容之后紧跟着如下宏指令:

/*
 * Pull in WINDOWS.H if necessary
 */
#ifndef _INC_WINDOWS
#include <windows.h>
#endif /* _INC_WINDOWS */

其作用是如果用户没有包含windows.h(_INC_WINDOWS在windows.h中定义)就自动包含它,以定义WinSock2.0所需的类型和常量等。

现在切换到windows.h,查找winsock,我们会惊奇的发现以下内容:

#ifndef WIN32_LEAN_AND_MEAN
#include <cderr.h>
#include <dde.h>
#include <ddeml.h>
#include <dlgs.h>
#ifndef _MAC
#include <lzexpand.h>
#include <mmsystem.h>
#include <nb30.h>
#include <rpc.h>
#endif
#include <shellapi.h>
#ifndef _MAC
#include <winperf.h>

 

#if(_WIN32_WINNT >= 0x0400)
#include <winsock2.h>
#include <mswsock.h>
#else
#include <winsock.h>
#endif /* _WIN32_WINNT >=  0x0400 */

#endif
// 这里省略掉一部分内容
#endif /* WIN32_LEAN_AND_MEAN */

看到没?windows.h会反向包含winsock2.h或者winsock.h!相互间的包含便是万恶之源!

下面具体分析一下问题是怎么发生的。

错误情形1:我们在自己的工程中先包含winsock2.h再包含windows.h,如果WIN32_LEAN_AND_MEAN未定义且_WIN32_WINNT大于或等于0x400,那么windows.h会在winsock2.h开头被自动引入,而windows.h又会自动引入mswsock.h,此时,mswsock.h里所用的socket类型还尚未定义,因此会出现类型未定义错误。

错误情形2:先包含windows.h再包含winsock2.h,如果WIN32_LEAN_AND_MEAN未定义且_WIN32_WINNT未定义或者其版本号小于0x400,那么windows.h会自动导入旧有的winsock.h,这样再当winsock2.h被包含时便会引起重定义。

这里要说明的是,宏WIN32_LEAN_AND_MEAN的作用是减小win32头文件尺寸以加快编译速度,一般由AppWizard在stdafx.h中自动定义。_WIN32_WINNT的作用是开启高版本操作系统下的特殊函数,比如要使用可等待定时器(WaitableTimer),就得要求_WIN32_WINNT的值大于或等于0x400。因此,如果你没有遇到上述两个问题,很可能是你没有在这些条件下进行网络编程。

问题还没有结束,要知道除了VC自带windows库文件外,MS的Platform SDK也含有这些头文件。我们很可能发现在之前能够好好编译的程序在改变了windows头文件包含路径后又出了问题。原因很简单,Platform SDK中的windows.h与VC自带的文件存在差异,其相同位置的代码如下:

#ifndef WIN32_LEAN_AND_MEAN
#include <cderr.h>
#include <dde.h>
#include <ddeml.h>
#include <dlgs.h>
#ifndef _MAC
#include <lzexpand.h>
#include <mmsystem.h>
#include <nb30.h>
#include <rpc.h>
#endif
#include <shellapi.h>
#ifndef _MAC
#include <winperf.h>
#include <winsock.h>  // 这里直接包含winsock.h
#endif
#ifndef NOCRYPT
#include <wincrypt.h>
#include <winefs.h>
#include <winscard.h>
#endif

 

#ifndef NOGDI
#ifndef _MAC
#include <winspool.h>
#ifdef INC_OLE1
#include <ole.h>
#else
#include <ole2.h>
#endif /* !INC_OLE1 */
#endif /* !MAC */
#include <commdlg.h>
#endif /* !NOGDI */
#endif /* WIN32_LEAN_AND_MEAN */

唉,我们不禁要问MS为什么要搞这么多花样,更让人气愤的是,既然代码不一样,windows.h里却没有任何一个宏定义能够帮助程序辨别当前使用的文件是VC自带的还是PSDK里的。

后来,我写了一个头文件专门处理winsock2.h的包含问题,名为winsock2i.h,只需在要使用WinSock2.0的源文件里第一个包含此文件即可,不过由于前面提到的问题,当使用PSDK时,需要手工定义一下USING_WIN_PSDK,源码如下:

//
// winsock2i.h - Include winsock2.h safely.
//
// Copyleft  02/24/2005  by freefalcon
//
//
// When WIN32_LEAN_AND_MEAN is not defined and _WIN32_WINNT is LESS THAN 0x400,
// if we include winsock2.h AFTER windows.h or winsock.h, we get some compiling
// errors as following:
//   winsock2.h(99) : error C2011: 'fd_set' : 'struct' type redefinition
//
// When WIN32_LEAN_AND_MEAN is not defined and _WIN32_WINNT is NOT LESS THAN 0x400,
// if we include winsock2.h BEFORE windows.h, we get some other compiling errors:
//   mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier
//
// So, this file is used to help us to include winsock2.h safely, it should be
// placed before any other header files.
//

 

#ifndef _WINSOCK2API_

// Prevent inclusion of winsock.h
#ifdef _WINSOCKAPI_
#error Header winsock.h is included unexpectedly.
#endif

// NOTE: If you use Windows Platform SDK, you should enable following definition:
// #define USING_WIN_PSDK

#if !defined(WIN32_LEAN_AND_MEAN) && (_WIN32_WINNT >= 0x0400) && !defined(USING_WIN_PSDK)
#include <windows.h>
#else
#include <winsock2.h>
#endif

#endif//_WINSOCK2API_

Windows环境下的C/C++ Socket网络编程报错解决办法 windows环境下的网络编程不同于linux中的网络编程,由于windows下涉及到编译器以及环境变量的配置,对新手来说会产生各种各样的问题。博主通过几天的调试运行,在几个IDE中进行了各种调试,最终将各种环境下的报错信息成功解决,希望能够对入门Socket的新手提供帮助。首先是windows环境下,提供了两个头文件和两个库文件:winsock.h 和 winsock2.h 以及wsock32.lib 和 ws2_32.lib。 阅读详情

相关推荐

Winsock2.h编译报错重定义冲突的解决方案

开发环境 编译器:VS2008 OS:Windows 10 报错信息 1>C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\ws2def.h(91) : warning C4005: “AF_IPX”: 宏重定义 1> C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\winsock.h(460) : 参见“AF_IPX”的前一个定义 1>C:\Program

yangzijiangtou 6442

C++<winsock2.h>链接时报错

【代码】C++<winsock2.h>链接时报错。

m0_46614261的博客 1246

MATLAB下pdf文件操作读取示例

当遇到一些需要大量数据的项目,数据的读取与储存显得尤为重要。怎样把数据从其他格式的文件中读取,并运用到程序中是很多时候我们要解决的问题。对于平常的.txt,和.xlsx文件,MATLAB有对应的函数帮助读取,但是遇到pdf文件时MATLAB很难读取内容。本文以一个操作实例提供了一个从pdf文件中读取数据的方法。

UESTC 五高考3模拟的博客 6536

用VScode 在Windows下写简单的socket通讯

用VScode 在Windows下写简单的socket通讯 最近在测试设备,需要用网口通信,第一次调试,中间遇到了很多问题,简单说一下吧。 (第一次发,如有问题,欢迎大家提出) 1、系统环境:Windows10; 2编译环境:VScode最新版本 3、语言:C/C++ 4、客户端例程 之前没有了解过socket通讯,在写例程的时候,查阅了很多资料,了解什么是客户端和服务端,此次我要用的仅是客户端。查询资料之后,自己试着写了一段,结果中间出了很多问题,下面一一进行展示: 问题1:编译,提示collect2.

oliver_xi的博客 1万+

Windowswinsock.h和winsock2.h

在同一个项目中最好不要同时使用winsock.h和winsock2.h 因为当winsock.h在winsock2.h前包含时,编译会报错,因为两个文件不能共存的很好。 Socketwinsock.h和winsock2.h的不同

qq_42113801的博客 1765

winsock开发重复定义问题

参考: VS2013使用winsock.h和winsock2.h发生冲突后的终极解决方法:http://www.cnblogs.com/Shirlies/p/5137548.html WINSOCK.H WINSOCK2.H的区别及函数重复定义的解决方法:http://blog.chinaunix.net/uid-24709751-id-4150975.html windows.h...

deo91209的博客 117

winsockwinsock2冲突

在初学Windows网络编程时,曾经遇到过两类编译错误(VC6的Build窗口哗哗的显示了102个Errors),都是些类型未定义或者重复定义问题,让我感到很郁闷。这两种错误情况下的第一条错误信息分别为:错误情形1:mswsock.h(69) : error C2065: 'SOCKET' : undeclared identifier错误情形2winsock2.h(99) : error...

weixin_30800987的博客 492

ws2tcpip winsock2 C2065 undeclared identifier visual studio 2019

ws2tcpip.h ws2def.h winsock2.h Visual Studio 2019 报错 redefinition 等等 error C2065: undeclared identifier error C3861: identifier not found? ws2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition error C3861: identifier not foun...

lsh的博客 825

'fd_set' redefinition winsock2.h,相关头文件条件编译处理

今天写一个TCP/IP的小程序的时候,偶然间发现一个错误工程类型:Win32 Console Application 错误如下:--------------------Configuration: TcpSer - Win32 Debug--------------------Compiling...main.cppd:/program files/microsoft visual

beckle_ye的专栏 2562

windows.h和winsock2.h解决办法

 最近用到  #include       #include      出现重定义的问题,网上大部分的解决方法是   在包含windows.h前需要定义一个宏,去除winsock.h  包含     #define   WIN32_LEAN_AND_MEAN     #include    但问题并未解决,后来在freefalcon的空间,找到了解决方法。 他

zhdrfirst的专栏 1917

C++ windows.h和WinSocket2.h的冲突

原因:同时两个引用重复定义宏 解决方法: 方法一:先引用 Winsock2.h 再引用 windows.h #include <Winsock2.h> #include<windows.h> 方法二:在引用之前,加上一句代码: #define WIN32_LEAN_AND_MEAN //这句代码可以避免重复引用 #include<windows.h> #include <Winsock2.h> 本文参考链接: C++Socket学习笔记—— windows

h799710的博客 1172

c语言 sys socket.h错误,系统的头文件mswsock.h报socket未定义异常什么情况求大神帮忙~多谢...

引用:F:\VC98\INCLUDE\mswsock.h(69):errorC2065:'SOCKET':undeclaredidentifierF:\VC98\INCLUDE\mswsock.h(69):errorC2146:syntaxerror:missing')'beforeidentifier's'F:\VC98\INCLUDE\mswsock.h(6...

weixin_33800724的博客 519

Winsock2.h或者ws2def.h大量重定义报错】

我的理解是,windows.h文件会包含Winsock.h,Winsock.h和Winsock2.h头文件中有定义冲突的部分,当用到Winsock2.h时就会冲突。所以调整头文件的顺序,将Winsock2.h包含在windows.h的前面。在每一个被涉及的项目,向属性-C/C+±预处理器-预处理器定义中,添加WIN32_LEAN_AND_MEAN,注意是每一个涉及的项目都要加。在c++的项目中引用mysql后,可能会出现大量重定义报错的问题,主要出现在Winsock2.h或者ws2def.h等文件里。

ldadadaaaa的博客 2593

#include <winsock2.h>报错的问题

#define PORT 5150 #define DATA_BUFSIZE 8192 typedef struct _SOCKET_INFORMATION { CHAR Buffer[DATA_BUFSIZE]; WSABUF DataBuf; SOCKET Socket; WSAOVERLAPPED Overlapped; DWORD BytesSEND; DWORD By

ghevinn欢迎您光临 9905

winsock2.h与ws2def.h等文件大量报错相关问题解决方法

问题: 最近在写网络编程相关内容,本来好好的代码写着写着就出现了大量错误 看了下文件,全都是winsock2、ws2def 、ws2ipdef、ws2tcpip内的报错 缘由: 我们知道,Windows网络编程至少需要两个头文件:winsock2.h和windows.h,而在WinSock2.0之前还存在一个老版本的winsock.h。正是这三个头文件的包含顺序,导致了上述问题的出现。 winsock2.h的内容,在文件开头有如下宏定义: #ifndef _WINSOCK2API_ #define _W

weixin_43956221的博客 9511

Windows 上的网络通信编程

本文是基于 MSDN 中的入门指导手册翻译和修改过来的

LikeShadow 2847

Windows下的网络编程Winsock

相比于基础,网络编程就要复杂一些,但其实也有固定格式,记住即可。

森明帮大于黑虎帮的博客 6881

从内参矩阵到归一化平面:揭秘相机成像的标准化核心

本文深入解析了相机成像中的核心概念——归一化平面。通过拆解内参矩阵(包含焦距、主点等参数)的作用,详细阐述了如何将像素坐标转换为与具体相机硬件无关的归一化坐标。这一标准化过程是计算机视觉算法(如多相机系统对齐、视觉SLAM)实现跨设备通用性的关键,能有效提升算法的鲁棒性和泛化能力。

opencv7vision的博客 431

基于PHP和JavaScript的CRM+收银+小程序+星球新改版台球后端设计源码

本项目为全面升级的台球后端系统源码,采用PHP和JavaScript开发,集成了CRM、收银、小程序和星球功能。源码共计228个文件,其中PHP文件202个,JavaScript文件3个,其他类型文件包括Git忽略文件、JSON、配置文件等。该系统旨在提供高效的管理解决方案,适用于台球行业的数字化运营需求。

上一篇: error LNK2001: unresolved external symbol
下一篇: 解决unresolved external symbol "public: int __thiscall CWnd::KillTimer(unsigned int)" (?KillTimer@CWnd@@QAEHI@Z)问题
SWenJing
博客等级 码龄18年 8粉丝 20原创
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值