使用mingw64(gcc版本11.3.0)编译一个64位软件,如下设置socket为非阻塞模式会失败:
1
2
3
4
5
u_long nb = 1;
ret = ioctlsocket(fd, FIONBIO, &nb);
if (ret) {
error = WSAGetLastError();
}
ret等于SOCKET_ERROR,error等于WSAEOPNOTSUPP(10045),chatgpt给不出有效信息。找到0x8004667E is what you get,试试真好了,看着是mingw中宏定义FIONBIO
和原生的不同。
Windows原生winsock2.h定义
1
2
3
4
5
6
7
8
9
10
11
12
#define IOCPARM_MASK 0x7f /* parameters must be < 128 bytes */
#define IOC_VOID 0x20000000 /* no parameters */
#define IOC_OUT 0x40000000 /* copy out parameters */
#define IOC_IN 0x80000000 /* copy in parameters */
#define IOC_INOUT (IOC_IN|IOC_OUT)
/* 0x20000000 distinguishes new &
old ioctl's */
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define FIONBIO _IOW('f', 126, u_long) /* set/clear non-blocking i/o */
mingw中winsock2.h定义
1
2
3
4
5
6
7
8
9
10
11
#define IOCPARM_MASK 0x7f
#define IOC_VOID 0x20000000
#define IOC_OUT 0x40000000
#define IOC_IN 0x80000000
#define IOC_INOUT (IOC_IN|IOC_OUT)
#define _IO(x,y) (IOC_VOID|((x)<<8)|(y))
#define _IOR(x,y,t) (IOC_OUT|(((__LONG32)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define _IOW(x,y,t) (IOC_IN|(((__LONG32)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
#define FIONBIO _IOW('f',126,u_long)
两者看上去存在__LONG32
和long
的不同,实测发现mingw64环境下FIONBIO
等于0x8008667E,而不是期望的0x8004667E,这是由于mingw64中u_long
是8个字节导致。