项目情况:
调用第三方网络库(hv库),在win7/8/10等系统都运行正常,在XP系统提示“ 无法定位程序输入点WSAPoll于动态链接库ws2_32.dll”
产生原因:
第三方网络库(hv库)使用到了wsapoll,inet_pton,inet_ntop等函数,这些函数是定义在系统库ws2_32.dll里面的,而XP系统的ws2_32.dll库并没有这些函数。这些函数在 Windows Vista 及更高版本上才被定义。
解决思路(可以直接看思路3):
思路1:最简单,更新系统呗,不用XP;等于没解决
思路2: 换系统库呗。我把win7以上的ws2_32.dll拷过去还不行?
①拷贝到C:\Windows\System32; 可以吗?不行,这里的库只有安全模式可以更改,总不能每台机器都整;
②拷贝到程序当前目录可以吗?不行。看下图,程序的的确确找到了WS2_32.DLL,但是WS2_32.DLL又依赖系统库MSVCRT.DLL,但是XP系统的MSVCRT.DLL,又缺少了win 7 WS2_32.DLL要调用的函数,所以就这样层层报错。我试过把win7的MSVCRT.DLL和依赖库全部拷过来,xp系统也会找C:\Windows\System32上面的MSVCRT.DLL,即使修改环境变量也不起效。


思路3: 改第三方网络库(hv库)的源码。不是报几个函数在XP的WS2_32.DLL没定义吗,那我自己写还不行吗?
①WSAPOLL函数,我参考thrift库重写(名字要修改不要重定义):
thrift库:Index of /dist/thrift 我用的是0.12.0
- typedef struct timeval2
- {
- double tv_sec; /* seconds */
- double tv_usec; /* microseconds */
- }timeval;
-
-
- # define THRIFT_POLLIN 0x0300
- # define THRIFT_POLLOUT 0x0010
- /// 需要屏蔽此行
- int thrift_poll1(WSAPOLLFD *fdArray, ULONG nfds, INT timeout)
- {
- fd_set read_fds, write_fds;
- fd_set* read_fds_ptr = NULL;
- fd_set* write_fds_ptr = NULL;
-
- FD_ZERO(&read_fds);
- FD_ZERO(&write_fds);
-
- for (ULONG i = 0; i
- //Read (in) socket
- if ((fdArray[i].events & THRIFT_POLLIN) == THRIFT_POLLIN) {
- read_fds_ptr = &read_fds;
- FD_SET(fdArray[i].fd, &read_fds);
- }
- //Write (out) socket
- if ((fdArray[i].events & THRIFT_POLLOUT) == THRIFT_POLLOUT) {
- write_fds_ptr = &write_fds;
- FD_SET(fdArray[i].fd, &write_fds);
- }
- }
-
- timeval time_out;
- timeval* time_out_ptr = NULL;
- if (timeout >= 0) {
- timeval time_out = { timeout / 1000, (timeout % 1000) * 1000 };
- time_out_ptr = &time_out;
- }
- else { //to avoid compiler warnings
- (void)time_out;
- (void)timeout;
- }
-
- int sktready = select(1, read_fds_ptr, write_fds_ptr, NULL, time_out_ptr);
- if (sktready > 0) {
- for (ULONG i = 0; i
- fdArray[i].revents = 0;
- if (FD_ISSET(fdArray[i].fd, &read_fds))
- fdArray[i].revents |= THRIFT_POLLIN;
- if (FD_ISSET(fdArray[i].fd, &write_fds))
- fdArray[i].revents |= THRIFT_POLLOUT;
- }
- }
- return sktready;
- }
-
- //WSAPOLL函数
- int WINAPI myWSAPoll(WSAPOLLFD *wfds, ULONG count, int timeout)
- {
- return thrift_poll1(wfds, count, timeout);
-
- }
②inet_pton和inet_ntop,我参考glibc库重写(名字要修改不要重定义):
glibc库:Index of /pub/gnu/glibc 我用的是glibc-2.36
inet_pton:
-
- #define NS_INADDRSZ 4 /*%< IPv4 T_A */
- #define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */
- #define NS_INT16SZ 2 /*%< #/bytes of data in a uint16_t */
-
- static int inet_pton4(const char *src, const char *end, unsigned char *dst)
- {
- int saw_digit; // 每个八位组是否遇到数字标记,新的八位组将会清除标记
- int octets; // 八位组的个数,ip地址合法,则为4个
- int ch; // 遍历字符串,每次获得的字符
- // NS_INADDRSZ长度是4个字节, 宏定义在nameser.h中
- // 注意tmp不是字符串,仅仅是用来存放4个字节的数据,无'\0'
- unsigned char tmp[NS_INADDRSZ];
- unsigned char *tp; // tp指的是八位组
-
- saw_digit = 0;
- octets = 0;
- *(tp = tmp) = 0; // *tp = 0;初始化必须为0,计算数值的时候会有依赖
-
- // 本函数实际上是转换成网络序的,所以方向是src -> end
- // 如果仅仅转换成二进制,方向是end -> src
- while (src < end)
- {
- ch = *src++; // 得到获得的ASCII值,src指向下一个字符
- if (ch >= '0' && ch <= '9')
- {
- // 八位组迭代,比如192.168.8.217
- // 以192为例:
- // 0 -> 0 * 10 + 1 = 1 -> 1 * 10 + 9 = 19 -> 19 * 10 + 2 = 192
- // 在将192赋值到tmp的第一个字节上(第一个八位组)
- unsigned int new = *tp * 10 + (ch - '0');
-
- // 八位组中不能以0开头,比如192.168.08.217是错误的
- if (saw_digit && *tp == 0)
- return 0;
- // 某一个八位组值不能超过255
- if (new > 255)
- return 0;
-
- // 八位组赋值
- *tp = new;
-
- // 一般是在遇到'.'的时候,(! saw_digit)为0
- // 而在'.'之后的第一个数字置为1
- // 统计八位组的数目,由于在运行中,所以值不得超过4
- if (!saw_digit)
- {
- if (++octets > 4)
- return 0;
- saw_digit = 1;
- }
- }
- else if (ch == '.' && saw_digit)
- {
- if (octets == 4)
- return 0;
-
- // 下一个八位组赋值,必须为0,方面迭代
- // saw_digit标记为未遇到数值
- *++tp = 0;
- saw_digit = 0;
- }
- else
- return 0; // 其他字符,直接返回错误
- }
- if (octets < 4)
- return 0;
- memcpy(dst, tmp, NS_INADDRSZ);
- return 1;
- }
-
- static int hex_digit_value(char ch)
- {
- if ('0' <= ch && ch <= '9')
- return ch - '0';
- if ('a' <= ch && ch <= 'f')
- return ch - 'a' + 10;
- if ('A' <= ch && ch <= 'F')
- return ch - 'A' + 10;
- return -1;
- }
-
- static int inet_pton6(const char *src, const char *src_endp, unsigned char *dst)
- {
- unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
- const char *curtok;
- int ch;
- size_t xdigits_seen; /* Number of hex digits since colon. */
- unsigned int val;
-
- tp = memset(tmp, '\0', NS_IN6ADDRSZ);
- endp = tp + NS_IN6ADDRSZ;
- colonp = NULL;
-
- /* Leading :: requires some special handling. */
- if (src == src_endp)
- return 0;
- if (*src == ':')
- {
- ++src;
- if (src == src_endp || *src != ':')
- return 0;
- }
-
- curtok = src;
- xdigits_seen = 0;
- val = 0;
- while (src < src_endp)
- {
- ch = *src++;
- int digit = hex_digit_value(ch);
- if (digit >= 0)
- {
- if (xdigits_seen == 4)
- return 0;
- val <<= 4;
- val |= digit;
- if (val > 0xffff)
- return 0;
- ++xdigits_seen;
- continue;
- }
- if (ch == ':')
- {
- curtok = src;
- if (xdigits_seen == 0)
- {
- if (colonp)
- return 0;
- colonp = tp;
- continue;
- }
- else if (src == src_endp)
- return 0;
- if (tp + NS_INT16SZ > endp)
- return 0;
- *tp++ = (unsigned char)(val >> 8) & 0xff;
- *tp++ = (unsigned char)val & 0xff;
- xdigits_seen = 0;
- val = 0;
- continue;
- }
- if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
- && inet_pton4(curtok, src_endp, tp) > 0)
- {
- tp += NS_INADDRSZ;
- xdigits_seen = 0;
- break; /* '\0' was seen by inet_pton4. */
- }
- return 0;
- }
- if (xdigits_seen > 0)
- {
- if (tp + NS_INT16SZ > endp)
- return 0;
- *tp++ = (unsigned char)(val >> 8) & 0xff;
- *tp++ = (unsigned char)val & 0xff;
- }
- if (colonp != NULL)
- {
- /* Replace :: with zeros. */
- if (tp == endp)
- /* :: would expand to a zero-width field. */
- return 0;
- size_t n = tp - colonp;
- memmove(endp - n, colonp, n);
- memset(colonp, 0, endp - n - colonp);
- tp = endp;
- }
- if (tp != endp)
- return 0;
- memcpy(dst, tmp, NS_IN6ADDRSZ);
- return 1;
- }
-
- int __inet_pton_length(int af, const char *src, size_t srclen, void *dst)
- {
- switch (af)
- {
- case AF_INET:
- return inet_pton4(src, src + srclen, dst);
- case AF_INET6:
- return inet_pton6(src, src + srclen, dst);
- default:
- //__set_errno(EAFNOSUPPORT);
- return -1;
- }
- }
-
- //inet_pton
- int __inet_pton(int af, const char *src, void *dst)
- {
- return __inet_pton_length(af, src, strlen(src), dst);
- }
inet_ntop:
-
- #ifdef SPRINTF_CHAR
- # define SPRINTF(x) strlen(sprintf/**/x)
- #else
- # define SPRINTF(x) ((size_t)sprintf x)
- #endif
- static const char *inet_ntop4(const u_char *src, char *dst, socklen_t size)
- {
- static const char fmt[] = "%u.%u.%u.%u";
- char tmp[sizeof "255.255.255.255"];
-
- if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) {
- //__set_errno(ENOSPC);
- return (NULL);
- }
- return strcpy(dst, tmp);
- }
-
- /* const char *
- * inet_ntop6(src, dst, size)
- * convert IPv6 binary address into presentation (printable) format
- * author:
- * Paul Vixie, 1996.
- */
- static const char *inet_ntop6(const u_char *src, char *dst, socklen_t size)
- {
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
- struct { int base, len; } best, cur;
- u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
- int i;
-
- /*
- * Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof words);
- for (i = 0; i < NS_IN6ADDRSZ; i += 2)
- words[i / 2] = (src[i] << 8) | src[i + 1];
- best.base = -1;
- cur.base = -1;
- best.len = 0;
- cur.len = 0;
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
- if (words[i] == 0) {
- if (cur.base == -1)
- cur.base = i, cur.len = 1;
- else
- cur.len++;
- }
- else {
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- cur.base = -1;
- }
- }
- }
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len)
- best = cur;
- }
- if (best.base != -1 && best.len < 2)
- best.base = -1;
-
- /*
- * Format the result.
- */
- tp = tmp;
- for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
- /* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base &&
- i < (best.base + best.len)) {
- if (i == best.base)
- *tp++ = ':';
- continue;
- }
- /* Are we following an initial run of 0x00s or any real hex? */
- if (i != 0)
- *tp++ = ':';
- /* Is this address an encapsulated IPv4? */
- if (i == 6 && best.base == 0 &&
- (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
- if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
- return (NULL);
- tp += strlen(tp);
- break;
- }
- tp += SPRINTF((tp, "%x", words[i]));
- }
- /* Was it a trailing run of 0x00's? */
- if (best.base != -1 && (best.base + best.len) ==
- (NS_IN6ADDRSZ / NS_INT16SZ))
- *tp++ = ':';
- *tp++ = '\0';
-
- /*
- * Check for overflow, copy, and we're done.
- */
- if ((socklen_t)(tp - tmp) > size) {
- //__set_errno(ENOSPC);
- return (NULL);
- }
- return strcpy(dst, tmp);
- }
-
-
- //inet_ntop
- const char *inet_ntop1(int af, const void *src, char *dst, socklen_t size)
- {
- switch (af) {
- case AF_INET:
- return (inet_ntop4(src, dst, size));
- case AF_INET6:
- return (inet_ntop6(src, dst, size));
- default:
- //__set_errno(EAFNOSUPPORT);
- return (NULL);
- }
- /* NOTREACHED */
- }
-
相关阅读:
JS-闭包的用法
创建vue3项目并引用elementui
基于JPBC的无证书聚合签名方案实现
认识 URL
测试架构需要具备哪些能力
(附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
【5w字】SpringBoot源码分析
usb 命名乱的一批,怎么破
视频转二维码简单技巧,适用多种视频格式
Java内存模型之JMM
-
原文地址:https://blog.csdn.net/yaojinjian1995/article/details/127926276