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
{
	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<nfds; 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<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_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 */
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值