winsock编程:关于因为头文件而报错的问题

winsock编程:关于因为头文件而报错的问题

本文介绍关于头文件#include<windows.h>放在#include<winsock.h>之前报错的问题。

源文件1中:

#include<windows.h>

#include<winsock2.h>

//...

//...

源文件2中:

#include<winsock.h>

#include<winsock2.h>

//...

//...

编译这两个源文件时,编译出错的内容如下:

definition of 'FD_SET'

...\winsock2.h(143) : error C2011: 'timeval' : 'struct' type redefinition

...\include\winsock2.h(199) : error C2011: 'hostent' : 'struct' type redefinition

...\winsock2.h(212) : error C2011: 'netent' : 'struct' type redefinition

........

报错的意思是所有与这两个头文件包含和socket接口有关的函数以及结构体等都提示这样的错误:redefinition(函数以及结构体等类型重复定义)。

报错的原因

在源文件1报错的原因

windows.h包含了winsock.hwinsock2.h(在老版本windows系统编译下只包含winsock.h头文件)。由于winsock.hwinsock2.h这两个头文件是不能共存的,因为这两个头文件都存在一些相同的某变量或者函数定义名称,在执行代码中创建了对象(该对象都属于winsock.hwinsock2.h的),利用该对象进行访问这两个头文件里面的信息,一旦出现一些变量的名称都相同,进而导致这些变量重复定义的错误。

在源文件2报错的原因

像源文件1报错的原因一样,由于winsock.hwinsock2.h是不能共存的,所以导致了重复定义的错误。

那么问题来了,为什么如下代码,却不会报错呢。

在源文件1中修改代码为:

#include<winsock2.h>

#include<windows.h>

//......

在源文件2中修改代码为:

#include<winsock2.h>

#include<winsock.h>

//....

为什么把winsock2.h放在winsock.h或者包含winsockwindows.h的前面,再编译这两个文件就不会出错呢?

先放着这个问题在一边暂时不思考,然后讲一下winsock.hwinsock2.h的主要区别。

winsock.h和winsock2.h相同点

1. winsock.hwinsock2.h都包含在同一个目录(如果在VC6.0环境下,包括windows.h,它们都在“...\Microsoft Visual Studio\VC98\Include”的文件夹里面)。

winsock.h和winsock2.h区别

1. 版本区别,winsock.h版本为1.1,而winsock2.h版本为2.0.

2. winsock2winsock的升级版,winsock2对于对于winsock来说是向下兼容的,由于因为兼容,winsock有的东西,winsock2都有。

3. winsock支持的协议比winsock要多。

4. winsock2引用了新的SPI接口。主要意义是为了打破提供者的透明,开发者可以自己编写SPI接口。

5. winsock2扩展了更多与winsock所没有的功能,比如说,扩展TCP/IP协议栈,URL以及网络安全控制等。

好了,理解了它们之间的关系,返回来看看那个不会报错的问题。

winsock2.h文件的部分内容

#ifndef _WINSOCK2API_

#define _WINSOCK2API_

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

//...

//...

#endif

说明:在winsock.h头文件提前定义winscok.h的目的是阻止windows.h文件里面#include<winsock.h>的定义以及在winsock.h文件的定义

winsock.h文件的部分内容

说明:进行宏定义WINSOCKAPI_,也就是引用winsock1.1版本

#ifndef _WINSOCKAPI_

#define _WINSOCKAPI_

windows.h文件部分内容

#if(_WIN32_WINNT >= 0x0400)/

#include <winsock2.h>

#include <mswsock.h>

#else

#include <winsock.h>

#endif /* _WIN32_WINNT >=  0x0400 */

说明:由于在VC6.0环境下,该条件不满足,所以只引用了winsock.h。然而在VS环境下查看不到有这部分内容,不过编译时默认引用了winsock.h,也许Visual Studio开发团队对其进行优化了吧。至于_WIN32_WINNT是什么,我不再深究讲述下去,在这里讨论没意义,有兴趣者自行研究。

没有报错的主要原因:

由于windows.h里面包含了winsock1.1winsock2.0这两个版本,但是windows编译的通常情况下是选择了winsock.h。首先引用了#include<winsock2.h>,由于winsock2.h头文件里“#define _WINSOCKAPI_  ”预定义了宏,如果系统再指向下一步#include<winsock.h>(或者#include<windows.h>),由于#ifdef语句判断了winsockwinsock2.h文件早就定义过,所以就不会重复再定义这个了。

如果说,引用winsock.h再在引用winsock2.h的话,winsock在其文件早就定义了,在winsock2.h当中,#ifdef判断的是winsock2.0有没有定义,显然是满足条件的,所以在定义winscok2.0宏的同时就会重复定义wiinsock1.1。所以,如果winsock2.h预先被引用的话,下一个winsock.h就不会被用到,这就是所谓的两者不能共存。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值