`
zxl7049
  • 浏览: 30276 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

php 类似腾讯的IP库

阅读更多
$IpLocation = new IpLocation('ipData/QQWry.Dat'); 
$ipInfo=$IpLocation->getlocation($ip);
print_r($ipInfo);
注意获取的数据编码为 gbk

class IpLocation 
{
	/**
	 * QQWry.Dat文件指针
	 * @var resource
	 */
	var $fp;
	
	/**
	 * 第一条IP记录的偏移地址
	 * @var int
	 */
	var $firstip;
	
	/**
	 * 最后一条IP记录的偏移地址
	 * @var int
	 */
	var $lastip;
	
	/**
	 * IP记录的总条数(不包含版本信息记录)
	 * @var int
	 */
	var $totalip;
    
	/**
	 * 返回读取的长整型数
	 * @access private
	 * @return int
	 */
	function getlong() 
	{
		$result = unpack('Vlong', fread($this->fp, 4));	//将读取的little-endian编码的4个字节转化为长整型数
		return $result['long'];
	}
    
	/**
	* 返回读取的3个字节的长整型数
	* @access private
	* @return int
	*/
	function getlong3() 
	{
		$result = unpack('Vlong', fread($this->fp, 3).chr(0));	//将读取的little-endian编码的3个字节转化为长整型数
		return $result['long'];
	}
    
	/**
	* 返回压缩后可进行比较的IP地址
	* @access private
	* @param string $ip
	* @return string
	*/
	function packip($ip) 
	{
		// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,
		// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
		return pack('N', intval(ip2long($ip)));			//intaval 获取变量的整数值
	}
    
	/**
	* 返回读取的字符串
	* @access private
	* @param string $data
	* @return string
	*/
	function getstring($data = "") 
	{
		$char = fread($this->fp, 1);
		while (ord($char) > 0)					// 字符串按照C格式保存,以\0结束 ord()得到字符的ASCII码
		{
			$data .= $char;				// 将读取的字符连接到给定字符串之后
			$char = fread($this->fp, 1);
		}
		return $data;
	}
    
	/**
	* 返回地区信息
	* @access private
	* @return string
	*/
	function getarea() 
	{
		$byte = fread($this->fp, 1);				// 标志字节
		switch (ord($byte)) {
			case 0:						// 没有区域信息
				$area = "";
				break;
			case 1:
			case 2:						// 标志字节为1或2,表示区域信息被重定向
				fseek($this->fp, $this->getlong3());
				$area = $this->getstring();
				break;
			default:					// 否则,表示区域信息没有被重定向
				$area = $this->getstring($byte);
				break;
		}
		return $area;
	}
    
	/**
	* 根据所给 IP 地址或域名返回所在地区信息
	* @access public
	* @param string $ip
	* @return array
	*/
	function getlocation($ip = '') 
	{
		if (!$this->fp) return null;				// 如果数据文件没有被正确打开,则直接返回空
		if($ip == '') $ip = $this->clientIp();
		$location['ip'] = gethostbyname($ip);			// 将输入的域名转化为IP地址
		$ip = $this->packip($location['ip']);			// 将输入的IP地址转化为可比较的IP地址
		
		$l = 0;                            				// 搜索的下边界
		$u = $this->totalip;            				// 搜索的上边界
		$findip = $this->lastip;        				// 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)
		while ($l <= $u)					// 当上边界小于下边界时,查找失败
		{
			$i = floor(($l + $u) / 2);			// 计算近似中间记录
			fseek($this->fp, $this->firstip + $i * 7);
			$beginip = strrev(fread($this->fp, 4));        // 获取中间记录的开始IP地址
			
			if ($ip < $beginip)         			// 用户的IP小于中间记录的开始IP地址时
			{
				$u = $i - 1;            			// 将搜索的上边界修改为中间记录减一
			}
			else 
			{
				fseek($this->fp, $this->getlong3());
				$endip = strrev(fread($this->fp, 4));	// 获取中间记录的结束IP地址
				if ($ip > $endip)			// 用户的IP大于中间记录的结束IP地址时
				{
					$l = $i + 1;			// 将搜索的下边界修改为中间记录加一
				}
				else					// 用户的IP在中间记录的IP范围内时
				{
					$findip = $this->firstip + $i * 7;
					break;				// 则表示找到结果,退出循环
				}
			}
		}
		
		/* 获取查找到的IP地理位置信息 */
		fseek($this->fp, $findip);
		$location['beginip'] = long2ip($this->getlong());	// 用户IP所在范围的开始地址
		$offset = $this->getlong3();
		fseek($this->fp, $offset);
		$location['endip'] = long2ip($this->getlong());	// 用户IP所在范围的结束地址
		$byte = fread($this->fp, 1);				// 标志字节
		switch (ord($byte)) 
		{
			case 1: 					// 标志字节为1,表示国家和区域信息都被同时重定向
				$countryOffset = $this->getlong3();	// 重定向地址
				fseek($this->fp, $countryOffset);
				$byte = fread($this->fp, 1);		// 标志字节
				switch (ord($byte)) 
				{
					case 2:				// 标志字节为2,表示国家信息又被重定向
						fseek($this->fp, $this->getlong3());
						$location['country'] = $this->getstring();
						fseek($this->fp, $countryOffset + 4);
						$location['area'] = $this->getarea();
						break;
					default:			// 否则,表示国家信息没有被重定向
						$location['country'] = $this->getstring($byte);
						$location['area'] = $this->getarea();
						break;
				}
				break;
			case 2: 					// 标志字节为2,表示国家信息被重定向
				fseek($this->fp, $this->getlong3());
				$location['country'] = $this->getstring();
				fseek($this->fp, $offset + 8);
				$location['area'] = $this->getarea();
				break;
			default:					// 否则,表示国家信息没有被重定向
				$location['country'] = $this->getstring($byte);
				$location['area'] = $this->getarea();
				break;
		}
		
		if ($location['country'] == " CZ88.NET")		// CZ88.NET表示没有有效信息
		{
			$location['country'] = "未知";
		}
		if ($location['area'] == " CZ88.NET") 
		{
			$location['area'] = "";
		}
		return $location;
	}
	
	/**
	 * 获取客户端IP地址
	 * */
	function clientIp(){
		if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
			$onlineip = getenv('HTTP_CLIENT_IP');
		} elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
			$onlineip = getenv('HTTP_X_FORWARDED_FOR');
		} elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
			$onlineip = getenv('REMOTE_ADDR');
		} elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
			$onlineip = $_SERVER['REMOTE_ADDR'];
		}
		preg_match("/[\d\.]{7,15}/", $onlineip, $onlineipmatches);
		$onlineip = $onlineipmatches[0] ? $onlineipmatches[0] : 'unknown';
		unset($onlineipmatches);
		return $onlineip;
	}
    
	/**
	 * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息
	 * @param string $filename
	 * @return IpLocation
	 */
	function IpLocation($filename = "") 
	{
		if(!$filename) $filename = dirname(__FILE__) . '/QQWry.Dat';
		if(!file_exists($filename)) exit('qqwry.dat is not exists!');
		if (($this->fp = @fopen($filename, 'rb')) !== false) 
		{
			$this->firstip = $this->getlong();
			$this->lastip = $this->getlong();
			$this->totalip = ($this->lastip - $this->firstip) / 7;
			register_shutdown_function(array(&$this, '_IpLocation'));
		}
	}
    
	/**
	* 析构函数,用于在页面执行结束后自动关闭打开的文件。
	*/
	function _IpLocation() 
	{
		fclose($this->fp);
	}
}

分享到:
评论

相关推荐

    java实现根据ip地址获取地理位置的代码分享

    在这个方法中,我们首先构造了一个URL对象,指向腾讯的IP查询接口,并通过`URLConnection`打开连接。然后,使用`BufferedReader`读取响应内容,将其存储到`StringBuffer`中。接下来,对返回的字符串进行解析,提取出...

    php面试题目及答案

    - `require_once` 和 `include_once` 分别与 `require` 和 `include` 类似,但它们会检查文件是否已经被包含过,如果已经包含,则不会重复包含。 #### 15. 如何设置PHP session的保存路径和生命周期? ```php $...

    PHP实例开发源码—茉莉QQ机器人源码 php版.zip

    这个项目可能是为了教学目的或者开发者自用,它提供了一个实践平台,帮助学习者或开发者理解如何在PHP中构建类似的自动化交互系统。 【标签】:“PHP” 标签“PHP”是这个项目的关键技术点,PHP是一种广泛使用的...

    php socket http

    ### 类似腾讯的Socket服务器 腾讯的Socket服务器可能涉及到更复杂的网络编程,如: 1. **多线程/多进程**:为了同时处理多个客户端的连接,服务器可能使用多线程或多进程模型,每个连接分配一个独立的线程或进程来...

    腾讯微博提示missing parameter errorcode 102 错误的解决方法

    在进行腾讯微博接口开发时,...同时,理解和遵循API的调用规则以及错误处理机制,对于避免类似问题至关重要。在进行接口开发时,仔细检查请求参数,参照官方文档,结合实际返回的错误信息进行调试,是解决问题的关键。

    易语言-利用E2EE制作远程验证码识别(腾讯网页验证码)

    标签“网络相关源码”表明此项目涉及网络通信和编程,因此,除了E2EE和图像处理,还可能涉及到TCP/IP协议、HTTP请求响应机制、服务器端脚本语言(如PHP、Python)以及数据库操作等知识。 在压缩包中的"腾讯验证码...

    某科技公司内部ppt企划方案;搜搜前端架构与优化.pptx

    - **DNS问题**:通过自建智能DNS和利用自有IP库来提升DNS解析的准确性。 - **访问速度**:搭建测速系统,监控网络状况,优化网络传输。 - **单点故障**:引入高可用性(HA)设计,减少故障转移的时间。 - **监控...

    基于微信小程序的成绩查询系统的设计与实现.pdf

    本系统服务器端部署在腾讯云上,利用了广泛使用的LAMP(Linux + Apache + MySQL + PHP)技术栈进行开发。Linux作为服务器的操作系统,提供了稳定的环境;Apache作为网页服务器,负责处理客户端发送的请求;MySQL作为...

    phpmyadmin在宝塔面板里进不去的解决方案

    此外,还需要检查阿里云(或腾讯云等其他云服务提供商)的安全组设置。如果888端口没有被加入到安全组的入站规则中,也需要进行相应的配置。加入规则时,通常目标地址设置为“*.*.*.*/0”以允许所有IP进行访问。完成...

    ecshop短信接口修改

    2. **第三方短信服务商**:许多商家会选择使用如阿里云、腾讯云等第三方短信服务,这些服务商通常提供更稳定、快速的短信发送服务,并且支持丰富的API功能,如批量发送、短信模板管理等。 3. **接口集成**:将第三...

    交友相亲社交网站模板支持手机wap版

    想建立一个交友,婚恋,征婚网站平台,让更多的人在自己的网站上交友找到配偶或者知已,或者想拥有一套类似世纪佳缘交友网页模板的人。 特色功能: 1、新增第三方合作网站登录模块,腾讯QQ和新浪微博,更加方便网友...

    美人鱼小说;包含前后端_微信小程序模板js代码前台前端H5页面源码+后台源码.rar

    1. **微信小程序**:微信小程序是一种轻量级的应用开发框架,由腾讯公司推出,用于在微信内部运行应用。它提供了丰富的API和组件,可以快速构建用户体验良好的移动应用。在这个项目中,前端部分主要是用微信小程序...

    测试那点事-nginx简介

    Nginx(发音类似于“engine X”),是一款开源的Web服务器,以其卓越的性能、稳定性及高效资源利用而闻名。这款软件不仅能够作为HTTP服务器使用,还可以作为反向代理服务器和IMAP/POP3/SMTP代理服务器。 #### 开发...

    微信小程序http连接访问解决方案的示例

    除了Java,其他编程语言如Python、Node.js或PHP也可以实现类似的功能。关键在于,服务器需要能够接收来自小程序的HTTPS请求,并通过HTTPS转发到HTTP API,同时接收返回的数据并回传给小程序。 总结起来,解决微信小...

Global site tag (gtag.js) - Google Analytics