900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > c++/VS XP系统 无法定位程序输入点WSAPoll于动态链接库ws2_32.dll解决方案

c++/VS XP系统 无法定位程序输入点WSAPoll于动态链接库ws2_32.dll解决方案

时间:2018-12-16 00:15:09

相关推荐

c++/VS XP系统 无法定位程序输入点WSAPoll于动态链接库ws2_32.dll解决方案

项目情况:

调用第三方网络库(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{doubletv_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<nfds; i++) {//Read (in) socketif ((fdArray[i].events & THRIFT_POLLIN) == THRIFT_POLLIN) {read_fds_ptr = &read_fds;FD_SET(fdArray[i].fd, &read_fds);}//Write (out) socketif ((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<nfds; 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_INADDRSZ4/*%< IPv4 T_A */#define NS_IN6ADDRSZ16/*%< IPv6 T_AAAA */#define NS_INT16SZ2/*%< #/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 -> srcwhile (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;// 某一个八位组值不能超过255if (new > 255)return 0;// 八位组赋值*tp = new;// 一般是在遇到'.'的时候,(! saw_digit)为0// 而在'.'之后的第一个数字置为1// 统计八位组的数目,由于在运行中,所以值不得超过4if (!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;}elsereturn 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_ptonint __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)#endifstatic 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;elsecur.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_ntopconst 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 */}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。