diff --git a/README.md b/README.md index d0251ecf..2a2ea553 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,11 @@ ip2region - 最自由的ip地址查询库,ip到地区的映射库,提供Bina ### 4. 多查询客户端的支持,0.0x毫秒级别的查询 -已经集成的客户端有:java, php, c, python,nodejs,php扩展(支持linux, php5, php7版本已支持),golang。 +已经集成的客户端有:java, C#, php, c, python,nodejs,php扩展(支持linux, php5, php7版本已支持),golang。 提供了两种查询算法,响应时间如下: 客户端/binary算法/b-tree算法/Memory算法: + c#/0.x毫秒/0.x毫秒/0.x毫秒 java/0.x毫秒/0.x毫秒/0.1x毫秒 (使用RandomAccessFile) php/0.x毫秒/0.1x毫秒/0.1x毫秒 c/0.0x毫秒/0.0x毫秒/0.00x毫秒(b-tree算法基本稳定在0.02x毫秒级别) @@ -37,8 +38,21 @@ maven仓库地址: 1.4 ``` +nuget安装命令 +```shell +Install-Package IP2Region +``` ### 5. 测试程序: +c#: +```shell +cd IP2Region_ConsoleTest +dotnet run +example result: +请输入IP地址: +36.149.160.55 +``` + java: ```shell cd binding/java diff --git a/binding/c#/IP2Region/DBSearcher.cs b/binding/c#/IP2Region/DBSearcher.cs new file mode 100644 index 00000000..ca5cf5a1 --- /dev/null +++ b/binding/c#/IP2Region/DBSearcher.cs @@ -0,0 +1,436 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +using System; +using System.IO; +using System.Text; + +namespace IP2Region +{ + public class DbSearcher + { + public static int BTREE_ALGORITHM = 1; + public static int BINARY_ALGORITHM = 2; + public static int MEMORY_ALGORITYM = 3; + + /** + * db config + */ + private DbConfig dbConfig = null; + + /** + * db file access handler + */ + private FileStream raf = null; + + /** + * header blocks buffer + */ + private long[] HeaderSip = null; + private int[] HeaderPtr = null; + private int headerLength; + + /** + * super blocks info + */ + private long firstIndexPtr = 0; + private long lastIndexPtr = 0; + private int totalIndexBlocks = 0; + + /** + * for memory mode + * the original db binary string + */ + private byte[] dbBinStr = null; + + /** + * construct class + * + * @param bdConfig + * @param dbFile + * @throws FileNotFoundException + */ + public DbSearcher(DbConfig dbConfig, String dbFile) + { + this.dbConfig = dbConfig; + raf = new FileStream(dbFile, FileMode.Open, FileAccess.Read); + } + + /** + * get the region with a int ip address with memory binary search algorithm + * + * @param ip + * @throws IOException + */ + public DataBlock MemorySearch(long ip) + { + int blen = IndexBlock.GetIndexBlockLength(); + if (dbBinStr == null) + { + dbBinStr = new byte[(int)raf.Length]; + raf.Seek(0L, SeekOrigin.Begin); + raf.Read(dbBinStr, 0, dbBinStr.Length); + + //initialize the global vars + firstIndexPtr = Util.getIntLong(dbBinStr, 0); + lastIndexPtr = Util.getIntLong(dbBinStr, 4); + totalIndexBlocks = (int)((lastIndexPtr - firstIndexPtr) / blen) + 1; + } + + //search the index blocks to define the data + int l = 0, h = totalIndexBlocks; + long sip, eip, dataptr = 0; + while (l <= h) + { + int m = (l + h) >> 1; + int p = (int)(firstIndexPtr + m * blen); + + sip = Util.getIntLong(dbBinStr, p); + if (ip < sip) + { + h = m - 1; + } + else + { + eip = Util.getIntLong(dbBinStr, p + 4); + if (ip > eip) + { + l = m + 1; + } + else + { + dataptr = Util.getIntLong(dbBinStr, p + 8); + break; + } + } + } + + //not matched + if (dataptr == 0) return null; + + //get the data + int dataLen = (int)((dataptr >> 24) & 0xFF); + int dataPtr = (int)((dataptr & 0x00FFFFFF)); + int city_id = (int)Util.getIntLong(dbBinStr, dataPtr); + String region = System.Text.Encoding.UTF8.GetString(dbBinStr, dataPtr + 4, dataLen - 4);//new String(dbBinStr, dataPtr + 4, dataLen - 4, Encoding.UTF8); + + return new DataBlock(city_id, region, dataPtr); + } + + /** + * get the region throught the ip address with memory binary search algorithm + * + * @param ip + * @return DataBlock + * @throws IOException +*/ + public DataBlock MemorySearch(String ip) + { + return MemorySearch(Util.ip2long(ip)); + } + + + /** + * get by index ptr + * + * @param indexPtr + * @throws IOException +*/ + public DataBlock GetByIndexPtr(long ptr) + { + raf.Seek(ptr, SeekOrigin.Begin); + byte[] + buffer = new byte[12]; + raf.Read(buffer, 0, buffer.Length); + //long startIp = Util.getIntLong(buffer, 0); + //long endIp = Util.getIntLong(buffer, 4); + long extra = Util.getIntLong(buffer, 8); + + int dataLen = (int)((extra >> 24) & 0xFF); + int dataPtr = (int)((extra & 0x00FFFFFF)); + + raf.Seek(dataPtr, SeekOrigin.Begin); + byte[] data = new byte[dataLen]; + raf.Read(data, 0, data.Length); + + int city_id = (int)Util.getIntLong(data, 0); + String region = Encoding.UTF8.GetString(data, 4, data.Length - 4); + //new String(data, 4, data.Length - 4, "UTF-8"); + + return new DataBlock(city_id, region, dataPtr); + } + + /** + * get the region with a int ip address with b-tree algorithm + * + * @param ip + * @throws IOException +*/ + public DataBlock BtreeSearch(long ip) + { + //check and load the header + if (HeaderSip == null) + { + raf.Seek(8L, SeekOrigin.Begin); //pass the super block + //byte[] b = new byte[dbConfig.getTotalHeaderSize()]; + byte[] b = new byte[4096]; + raf.Read(b, 0, b.Length); + + //fill the header + int len = b.Length >> 3, idx = 0; //b.lenght / 8 + HeaderSip = new long[len]; + HeaderPtr = new int[len]; + long startIp, dataPtrTemp; + for (int i = 0; i < b.Length; i += 8) + { + startIp = Util.getIntLong(b, i); + dataPtrTemp = Util.getIntLong(b, i + 4); + if (dataPtrTemp == 0) break; + + HeaderSip[idx] = startIp; + HeaderPtr[idx] = (int)dataPtrTemp; + idx++; + } + + headerLength = idx; + } + + //1. define the index block with the binary search + if (ip == HeaderSip[0]) + { + return GetByIndexPtr(HeaderPtr[0]); + } + else if (ip == HeaderSip[headerLength - 1]) + { + return GetByIndexPtr(HeaderPtr[headerLength - 1]); + } + + int l = 0, h = headerLength, sptr = 0, eptr = 0; + while (l <= h) + { + int m = (l + h) >> 1; + + //perfetc matched, just return it + if (ip == HeaderSip[m]) + { + if (m > 0) + { + sptr = HeaderPtr[m - 1]; + eptr = HeaderPtr[m]; + } + else + { + sptr = HeaderPtr[m]; + eptr = HeaderPtr[m + 1]; + } + + break; + } + + //less then the middle value + if (ip < HeaderSip[m]) + { + if (m == 0) + { + sptr = HeaderPtr[m]; + eptr = HeaderPtr[m + 1]; + break; + } + else if (ip > HeaderSip[m - 1]) + { + sptr = HeaderPtr[m - 1]; + eptr = HeaderPtr[m]; + break; + } + h = m - 1; + } + else + { + if (m == headerLength - 1) + { + sptr = HeaderPtr[m - 1]; + eptr = HeaderPtr[m]; + break; + } + else if (ip <= HeaderSip[m + 1]) + { + sptr = HeaderPtr[m]; + eptr = HeaderPtr[m + 1]; + break; + } + l = m + 1; + } + } + + //match nothing just stop it + if (sptr == 0) return null; + + //2. search the index blocks to define the data + int blockLen = eptr - sptr, blen = IndexBlock.GetIndexBlockLength(); + byte[] + iBuffer = new byte[blockLen + blen]; //include the right border block + raf.Seek(sptr, SeekOrigin.Begin); + raf.Read(iBuffer, 0, iBuffer.Length); + + l = 0; h = blockLen / blen; + long sip, eip, dataptr = 0; + while (l <= h) + { + int m = (l + h) >> 1; + int p = m * blen; + sip = Util.getIntLong(iBuffer, p); + if (ip < sip) + { + h = m - 1; + } + else + { + eip = Util.getIntLong(iBuffer, p + 4); + if (ip > eip) + { + l = m + 1; + } + else + { + dataptr = Util.getIntLong(iBuffer, p + 8); + break; + } + } + } + + //not matched + if (dataptr == 0) return null; + + //3. get the data + int dataLen = (int)((dataptr >> 24) & 0xFF); + int dataPtr = (int)((dataptr & 0x00FFFFFF)); + + raf.Seek(dataPtr, SeekOrigin.Begin); + byte[] data = new byte[dataLen]; + raf.Read(data, 0, data.Length); + + int city_id = (int)Util.getIntLong(data, 0); + String region = Encoding.UTF8.GetString(data, 4, data.Length - 4);// new String(data, 4, data.Length - 4, "UTF-8"); + + return new DataBlock(city_id, region, dataPtr); + } + + /** + * get the region throught the ip address with b-tree search algorithm + * + * @param ip + * @return DataBlock + * @throws IOException + */ + public DataBlock BtreeSearch(String ip) + { + return BtreeSearch(Util.ip2long(ip)); + } + + /** + * get the region with a int ip address with binary search algorithm + * + * @param ip + * @throws IOException +*/ + public DataBlock BinarySearch(long ip) + { + int blen = IndexBlock.GetIndexBlockLength(); + if (totalIndexBlocks == 0) + { + raf.Seek(0L, SeekOrigin.Begin); + byte[] superBytes = new byte[8]; + raf.Read(superBytes, 0, superBytes.Length); + //initialize the global vars + firstIndexPtr = Util.getIntLong(superBytes, 0); + lastIndexPtr = Util.getIntLong(superBytes, 4); + totalIndexBlocks = (int)((lastIndexPtr - firstIndexPtr) / blen) + 1; + } + + //search the index blocks to define the data + int l = 0, h = totalIndexBlocks; + byte[] + buffer = new byte[blen]; + long sip, eip, dataptr = 0; + while (l <= h) + { + int m = (l + h) >> 1; + raf.Seek(firstIndexPtr + m * blen, SeekOrigin.Begin); //set the file pointer + raf.Read(buffer, 0, buffer.Length); + sip = Util.getIntLong(buffer, 0); + if (ip < sip) + { + h = m - 1; + } + else + { + eip = Util.getIntLong(buffer, 4); + if (ip > eip) + { + l = m + 1; + } + else + { + dataptr = Util.getIntLong(buffer, 8); + break; + } + } + } + + //not matched + if (dataptr == 0) return null; + + //get the data + int dataLen = (int)((dataptr >> 24) & 0xFF); + int dataPtr = (int)((dataptr & 0x00FFFFFF)); + + raf.Seek(dataPtr, SeekOrigin.Begin); + byte[] data = new byte[dataLen]; + raf.Read(data, 0, data.Length); + + int city_id = (int)Util.getIntLong(data, 0); + String region = Encoding.UTF8.GetString(data, 4, data.Length - 4);//new String(data, 4, data.Length - 4, "UTF-8"); + + return new DataBlock(city_id, region, dataPtr); + } + + /** + * get the region throught the ip address with binary search algorithm + * + * @param ip + * @return DataBlock + * @throws IOException + */ + public DataBlock BinarySearch(String ip) + { + return BinarySearch(Util.ip2long(ip)); + } + + /** + * get the db config + * + * @return DbConfig +*/ + public DbConfig GetDbConfig() + { + return dbConfig; + } + + /** + * close the db + * + * @throws IOException +*/ + public void Close() + { + HeaderSip = null; //let gc do its work + HeaderPtr = null; + dbBinStr = null; + raf.Close(); + } + + } + +} \ No newline at end of file diff --git a/binding/c#/IP2Region/DataBlock.cs b/binding/c#/IP2Region/DataBlock.cs new file mode 100644 index 00000000..99cc4ad3 --- /dev/null +++ b/binding/c#/IP2Region/DataBlock.cs @@ -0,0 +1,92 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +using System; +using System.Text; + +namespace IP2Region +{ + public class DataBlock + { + /** + * city id + */ + private int city_id; + + /** + * region address + */ + private String region; + + /** + * region ptr in the db file + */ + private int dataPtr; + + /** + * construct method + * + * @param city_id + * @param region region string + * @param ptr data ptr + */ + public DataBlock(int city_id, String region, int dataPtr) + { + this.city_id = city_id; + this.region = region; + this.dataPtr = dataPtr; + } + + public DataBlock(int city_id, String region) + { + this.city_id = city_id; + this.region = region; + this.dataPtr = 0; + } + + public int GetCityId() + { + return city_id; + } + + public DataBlock SetCityId(int city_id) + { + this.city_id = city_id; + return this; + } + + public String GetRegion() + { + return region; + } + + public DataBlock SetRegion(String region) + { + this.region = region; + return this; + } + + public int GetDataPtr() + { + return dataPtr; + } + + public DataBlock SetDataPtr(int dataPtr) + { + this.dataPtr = dataPtr; + return this; + } + + public override String ToString() + { + StringBuilder sb = new StringBuilder(); + + sb.Append(city_id).Append('|').Append(region).Append('|').Append(dataPtr); + return sb.ToString(); + } + + } + +} diff --git a/binding/c#/IP2Region/DbConfig.cs b/binding/c#/IP2Region/DbConfig.cs new file mode 100644 index 00000000..830b4fd5 --- /dev/null +++ b/binding/c#/IP2Region/DbConfig.cs @@ -0,0 +1,69 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +using System; + +namespace IP2Region +{ + public class DbConfig + { + /** + * total header data block size + */ + private int totalHeaderSize; + + /** + * max index data block size + * u should always choice the fastest read block size + */ + private int indexBlockSize; + + /** + * construct method + * + * @param totalHeaderSize + * @param dataBlockSize + * @throws DbMakerConfigException + */ + public DbConfig(int totalHeaderSize) + { + if ((totalHeaderSize % 8) != 0) + { + throw new DbMakerConfigException("totalHeaderSize must be times of 8"); + } + this.totalHeaderSize = totalHeaderSize; + this.indexBlockSize = 8192; //4 * 2048 + } + + public DbConfig() + { + this.totalHeaderSize = 8 * 2048; + this.indexBlockSize = 8192; + } + + public int GetTotalHeaderSize() + { + return totalHeaderSize; + } + + public DbConfig SetTotalHeaderSize(int totalHeaderSize) + { + this.totalHeaderSize = totalHeaderSize; + return this; + } + + public int GetIndexBlockSize() + { + return indexBlockSize; + } + + public DbConfig SetIndexBlockSize(int dataBlockSize) + { + this.indexBlockSize = dataBlockSize; + return this; + } + } + +} \ No newline at end of file diff --git a/binding/c#/IP2Region/DbMakerConfigException.cs b/binding/c#/IP2Region/DbMakerConfigException.cs new file mode 100644 index 00000000..9c25ac2c --- /dev/null +++ b/binding/c#/IP2Region/DbMakerConfigException.cs @@ -0,0 +1,16 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +namespace IP2Region +{ + public class DbMakerConfigException : System.Exception + { + public string ErrorCode { get; set; } + public DbMakerConfigException(string ErrorCode) + { + this.ErrorCode=ErrorCode; + } + } +} \ No newline at end of file diff --git a/binding/c#/IP2Region/HeaderBlock.cs b/binding/c#/IP2Region/HeaderBlock.cs new file mode 100644 index 00000000..095014b9 --- /dev/null +++ b/binding/c#/IP2Region/HeaderBlock.cs @@ -0,0 +1,73 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* + +using System; + +namespace IP2Region +{ + + public class HeaderBlock + { + /** + * index block start ip address + */ + private long indexStartIp; + + /** + * ip address + */ + private int indexPtr; + + public HeaderBlock(long indexStartIp, int indexPtr) + { + this.indexStartIp = indexStartIp; + this.indexPtr = indexPtr; + } + + public long GetIndexStartIp() + { + return indexStartIp; + } + + public HeaderBlock SetIndexStartIp(long indexStartIp) + { + this.indexStartIp = indexStartIp; + return this; + } + + public int GetIndexPtr() + { + return indexPtr; + } + + public HeaderBlock SetIndexPtr(int indexPtr) + { + this.indexPtr = indexPtr; + return this; + } + + /** + * get the bytes for db storage + * + * @return byte[] + */ + public byte[] GetBytes() + { + /* + * +------------+-----------+ + * | 4bytes | 4bytes | + * +------------+-----------+ + * start ip index ptr + */ + byte[] b = new byte[8]; + + Util.writeIntLong(b, 0, indexStartIp); + Util.writeIntLong(b, 4, indexPtr); + + return b; + } + } +} \ No newline at end of file diff --git a/binding/c#/IP2Region/IP2Region.csproj b/binding/c#/IP2Region/IP2Region.csproj new file mode 100644 index 00000000..00fa2b27 --- /dev/null +++ b/binding/c#/IP2Region/IP2Region.csproj @@ -0,0 +1,22 @@ + + + + netstandard2.0;net46 + true + Rocher + Rocher + 准确率99.9%的ip地址定位库,0.0x毫秒级查询, 支持Binary,B树,内存三种查询算法,妈妈再也不用担心我的ip地址定位! + ip2region - 最自由的ip地址查询库,ip到地区的映射库,提供Binary,B树和纯内存三种查询算法,妈妈再也不用担心我的ip地址定位。 + Rocher + ip2region c# IP + https://gitee.com/rocherkong/IP2Region + 1.1.0 + + + + + Always + + + + diff --git a/binding/c#/IP2Region/IndexBlock.cs b/binding/c#/IP2Region/IndexBlock.cs new file mode 100644 index 00000000..7b5319bc --- /dev/null +++ b/binding/c#/IP2Region/IndexBlock.cs @@ -0,0 +1,117 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +using System; + +namespace IP2Region +{ + + public class IndexBlock + { + private static int LENGTH = 12; + + /** + * start ip address + */ + private long startIp; + + /** + * end ip address + */ + private long endIp; + + /** + * data ptr and data length + */ + private uint dataPtr; + + /** + * data length + */ + private int dataLen; + + public IndexBlock(long startIp, long endIp, uint dataPtr, int dataLen) + { + this.startIp = startIp; + this.endIp = endIp; + this.dataPtr = dataPtr; + this.dataLen = dataLen; + } + + public long GetStartIp() + { + return startIp; + } + + public IndexBlock SetStartIp(long startIp) + { + this.startIp = startIp; + return this; + } + + public long GetEndIp() + { + return endIp; + } + + public IndexBlock SetEndIp(long endIp) + { + this.endIp = endIp; + return this; + } + + public uint GetDataPtr() + { + return dataPtr; + } + + public IndexBlock SetDataPtr(uint dataPtr) + { + this.dataPtr = dataPtr; + return this; + } + + public int GetDataLen() + { + return dataLen; + } + + public IndexBlock SetDataLen(int dataLen) + { + this.dataLen = dataLen; + return this; + } + + public static int GetIndexBlockLength() + { + return LENGTH; + } + + /** + * get the bytes for storage + * + * @return byte[] + */ + public byte[] GetBytes() + { + /* + * +------------+-----------+-----------+ + * | 4bytes | 4bytes | 4bytes | + * +------------+-----------+-----------+ + * start ip end ip data ptr + len + */ + byte[] b = new byte[12]; + + Util.writeIntLong(b, 0, startIp); //start ip + Util.writeIntLong(b, 4, endIp); //end ip + + //write the data ptr and the length + long mix = dataPtr | ((dataLen << 24) & 0xFF000000L); + Util.writeIntLong(b, 8, mix); + + return b; + } + } +} \ No newline at end of file diff --git a/binding/c#/IP2Region/Util.cs b/binding/c#/IP2Region/Util.cs new file mode 100644 index 00000000..7d526d49 --- /dev/null +++ b/binding/c#/IP2Region/Util.cs @@ -0,0 +1,162 @@ +//******************************* +// Create By Rocher Kong +// Github https://github.com/RocherKong +// Date 2018.02.09 +//******************************* +using System; +using System.Globalization; +using System.Text; + +namespace IP2Region +{ + + public class Util + { + /** + * write specfield bytes to a byte array start from offset + * + * @param b + * @param offset + * @param v + * @param bytes + */ + public static void write(byte[] b, int offset, ulong v, int bytes) + { + for (int i = 0; i < bytes; i++) + { + b[offset++] = (byte)((v >> (8 * i)) & 0xFF); + } + } + + /** + * write a int to a byte array + * + * @param b + * @param offet + * @param v + */ + public static void writeIntLong(byte[] b, int offset, long v) + { + b[offset++] = (byte)((v >> 0) & 0xFF); + b[offset++] = (byte)((v >> 8) & 0xFF); + b[offset++] = (byte)((v >> 16) & 0xFF); + b[offset] = (byte)((v >> 24) & 0xFF); + } + + /** + * get a int from a byte array start from the specifiled offset + * + * @param b + * @param offset + */ + public static long getIntLong(byte[] b, int offset) + { + return ( + ((b[offset++] & 0x000000FFL)) | + ((b[offset++] << 8) & 0x0000FF00L) | + ((b[offset++] << 16) & 0x00FF0000L) | + ((b[offset] << 24) & 0xFF000000L) + ); + } + + /** + * get a int from a byte array start from the specifield offset + * + * @param b + * @param offset + */ + public static int getInt3(byte[] b, int offset) + { + return ( + (b[offset++] & 0x000000FF) | + (b[offset++] & 0x0000FF00) | + (b[offset] & 0x00FF0000) + ); + } + + public static int getInt2(byte[] b, int offset) + { + return ( + (b[offset++] & 0x000000FF) | + (b[offset] & 0x0000FF00) + ); + } + + public static int getInt1(byte[] b, int offset) + { + return ( + (b[offset] & 0x000000FF) + ); + } + + /** + * string ip to long ip + * + * @param ip + * @return long + */ + public static long ip2long(string ip) + { + string[] p = ip.Split('.'); + if (p.Length != 4) return 0; + var bip1 = long.TryParse(p[0], out long ip1); + var bip2 = long.TryParse(p[1], out long ip2); + var bip3 = long.TryParse(p[2], out long ip3); + var bip4 = long.TryParse(p[3], out long ip4); + + if (!bip1 || !bip2 || !bip3 || !bip4 + || ip4 > 255 || ip1 > 255 || ip2 > 255 || ip3 > 255 + || ip4 < 1 || ip1 < 1 || ip2 < 1 || ip3 < 1) + { + throw new Exception("IP Illegal."); + } + + long p1 = ((ip1 << 24) & 0xFF000000); + long p2 = ((ip2 << 16) & 0x00FF0000); + long p3 = ((ip3 << 8) & 0x0000FF00); + long p4 = ((ip4 << 0) & 0x000000FF); + return ((p1 | p2 | p3 | p4) & 0xFFFFFFFFL); + } + + /** + * int to ip string + * + * @param ip + * @return string + */ + public static string long2ip(long ip) + { + StringBuilder sb = new StringBuilder(); + + sb + .Append((ip >> 24) & 0xFF).Append('.') + .Append((ip >> 16) & 0xFF).Append('.') + .Append((ip >> 8) & 0xFF).Append('.') + .Append((ip >> 0) & 0xFF); + + return sb.ToString(); + } + + /** + * check the validate of the specifeld ip address + * + * @param ip + * @return boolean + */ + public static Boolean isIpAddress(string ip) + { + string[] p = ip.Split('.'); + if (p.Length != 4) return false; + + foreach (string pp in p) + { + if (pp.Length > 3) return false; + int val = int.Parse(pp); + if (val > 255) return false; + } + + return true; + } + } + +} \ No newline at end of file diff --git a/binding/c#/IP2Region_ConsoleTest/DBFile/ip2region.db b/binding/c#/IP2Region_ConsoleTest/DBFile/ip2region.db new file mode 100644 index 00000000..0bb25f6e Binary files /dev/null and b/binding/c#/IP2Region_ConsoleTest/DBFile/ip2region.db differ diff --git a/binding/c#/IP2Region_ConsoleTest/IP2Region_ConsoleTest.csproj b/binding/c#/IP2Region_ConsoleTest/IP2Region_ConsoleTest.csproj new file mode 100644 index 00000000..cef353f5 --- /dev/null +++ b/binding/c#/IP2Region_ConsoleTest/IP2Region_ConsoleTest.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp2.0 + + + + + + + + + C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\netstandard.library\2.0.1\build\netstandard2.0\ref\netstandard.dll + + + + + + Always + + + + diff --git a/binding/c#/IP2Region_ConsoleTest/Program.cs b/binding/c#/IP2Region_ConsoleTest/Program.cs new file mode 100644 index 00000000..722815c3 --- /dev/null +++ b/binding/c#/IP2Region_ConsoleTest/Program.cs @@ -0,0 +1,50 @@ +using IP2Region; +using System; +using System.Diagnostics; + +namespace IP2Region_ConsoleTest +{ + class Program + { + static void Main(string[] args) + { + DbSearcher dbSearcher = new DbSearcher(new DbConfig + { + + }, AppContext.BaseDirectory + @"/DBFile/ip2region.db"); + string ipAddress = ""; + DataBlock result = null, result2 = null,result3=null; + Console.WriteLine("请输入IP地址:"); + ipAddress = Console.ReadLine(); + Stopwatch sw = new Stopwatch(); + do + { + sw.Start(); + try + { + result = dbSearcher.BtreeSearch(ipAddress); + sw.Stop(); + Console.WriteLine("[btree]你的IP所属区域为:" + result.GetRegion() + ";耗时:" + sw.Elapsed.TotalMilliseconds + "ms"); + sw.Start(); + result2 = dbSearcher.BinarySearch(ipAddress); + sw.Stop(); + Console.WriteLine("[binarySearch]你的IP所属区域为:" + result2.GetRegion() + ";耗时:" + sw.Elapsed.TotalMilliseconds + "ms"); + sw.Start(); + result3 = dbSearcher.MemorySearch(ipAddress); + sw.Stop(); + Console.WriteLine("[MemorySearch]你的IP所属区域为:" + result3.GetRegion() + ";耗时:" + sw.Elapsed.TotalMilliseconds + "ms"); + Console.WriteLine("请输入IP地址:"); + } + catch (Exception ex) + { + + Console.WriteLine(ex.Message); + sw.Stop(); + } + + //Console.WriteLine("结束请输入bye"); + + } while ((ipAddress = Console.ReadLine()) != "bye"); + } + } +} diff --git a/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml b/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 00000000..548b9afb --- /dev/null +++ b/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,13 @@ + + + + + FileSystem + Release + netcoreapp2.0 + bin\Release\PublishOutput + + \ No newline at end of file diff --git a/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml.user b/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml.user new file mode 100644 index 00000000..4c24a800 --- /dev/null +++ b/binding/c#/IP2Region_ConsoleTest/Properties/PublishProfiles/FolderProfile.pubxml.user @@ -0,0 +1,7 @@ + + + + \ No newline at end of file