أفكار لإدارة IP والمنافذ بتنسيق المفتاح/القيمة؟

StackOverflow https://stackoverflow.com/questions/1546528

  •  20-09-2019
  •  | 
  •  

سؤال

أنا أبحث عن جيد و سريع طريقة لإدارة عناوين IP والمنافذ في ملف. نوع من جدول DB الذي يحتوي على عمودين: IP والمنفذ ، ولكن في ملف ، دون استخدام DB.

يجب أن تدعم إضافة وحذف وتحديث. لا يهمني من التزامن.

هل كانت مفيدة؟

المحلول

أدناه ، يأتي البعض لإكمال مهمتك. حاولت الذهاب بدقة إلى هذه النقطة ، لذلك ربما يكون هناك شيء مفقود.

سأقوم بإنشاء فئة "سجل" ، للحفاظ على أزواج IP/المنفذ

class Record : IPEndPoint, IComparable<Record>
{
    internal long Offset { get; set; }
    public bool Deleted  { get; internal set; }

    public Record() : base(0, 0)
    { 
        Offset = -1;
        Deleted = false;
    }

    public int CompareTo(Record other)
    {
        if (this.Address == other.Address && this.Address == other.Address )
            return 0;
        else if (this.Address == other.Address)
            return this.Port.CompareTo(other.Port);
        else
            return 
              BitConverter.ToInt32(this.Address.GetAddressBytes(), 0).CompareTo(
              BitConverter.ToInt32(other.Address.GetAddressBytes(), 0));
    }
}

class RecordComparer : IComparer<Record>
{
    public int Compare(Record x, Record y)
    {
        return x.CompareTo(y);
    }
}

... وفئة "DatabaseFile" لإدارة تفاعل DataFile.

class DatabaseFile : IDisposable
{
    private FileStream file;
    private static int RecordSize = 7;
    private static byte[] Deleted = new byte[] { 42 };
    private static byte[] Undeleted = new byte[] { 32 };
    public DatabaseFile(string filename)
    {
        file = new FileStream(filename, 
            FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
    }

    public IEnumerable<Record> Locate(Predicate<Record> record)
    {
        file.Seek(0, SeekOrigin.Begin);
        while (file.Position < file.Length)
        {
            long offset = file.Position;
            byte[] buffer = new byte[DatabaseFile.RecordSize];
            file.Read(buffer, 0, DatabaseFile.RecordSize);
            Record current = Build(offset, buffer);
            if (record.Invoke(current))
                yield return current;
        }
    }

    public void Append(Record record)
    {
        // should I look for duplicated values? i dunno
        file.Seek(0, SeekOrigin.End);
        record.Deleted = false;
        record.Offset = file.Position;
        Write(record);
    }

    public void Delete(Record record)
    {
        if (record.Offset == -1) return;
        file.Seek(record.Offset, SeekOrigin.Begin);
        record.Deleted = true;
        Write(record);
    }

    public void Update(Record record)
    {
        if (record.Offset == -1)
        {
            Append(record);
        }
        else
        {
            file.Seek(record.Offset, SeekOrigin.Begin);
            Write(record);
        }
    }

    private void Write(Record record)
    {
        file.Write(GetBytes(record), 0, DatabaseFile.RecordSize);
    }

    private Record Build(long offset, byte[] data)
    {
        byte[] ipAddress = new byte[4];
        Array.Copy(data, 1, ipAddress, 0, ipAddress.Length);
        return new Record
        {
            Offset = offset,
            Deleted = (data[0] == DatabaseFile.Deleted[0]),
            Address = new IPAddress(ipAddress), 
            Port = BitConverter.ToInt16(data, 5)
        };
    }

    private byte[] GetBytes(Record record)
    {
        byte[] returnValue = new byte[DatabaseFile.RecordSize];
        Array.Copy(
            record.Deleted ? DatabaseFile.Deleted : DatabaseFile.Undeleted, 0, 
            returnValue, 0, 1);
        Array.Copy(record.Address.GetAddressBytes(), 0, 
            returnValue, 1, 4);
        Array.Copy(BitConverter.GetBytes(record.Port), 0, 
            returnValue, 5, 2);
        return returnValue;
    }

    public void Pack()
    {
        long freeBytes = 0;
        byte[] buffer = new byte[RecordSize];
        Queue<long> deletes = new Queue<long>();

        file.Seek(0, SeekOrigin.Begin);
        while (file.Position < file.Length)
        {
            long offset = file.Position;
            file.Read(buffer, 0, RecordSize);
            if (buffer[0] == Deleted[0])
            {
                deletes.Enqueue(offset);
                freeBytes += RecordSize;
            }
            else
            {
                if (deletes.Count > 0)
                {
                    deletes.Enqueue(offset);
                    file.Seek(deletes.Dequeue(), SeekOrigin.Begin);
                    file.Write(buffer, 0, RecordSize);
                    file.Seek(offset + RecordSize, SeekOrigin.Begin);
                }
            }
        }
        file.SetLength(file.Length - freeBytes);
    }

    public void Sort()
    {
        int offset = -RecordSize; // lazy method
        List<Record> records = this.Locate(r => true).ToList();
        records.Sort(new RecordComparer());
        foreach (Record record in records)
        {
            record.Offset = offset += RecordSize;
            Update(record);
        }
    }

    public void Dispose()
    {
        if (file != null)
            file.Close();
    }
}

أدناه ، مثال عمل:

static void Main(string[] args)
{
    List<IPEndPoint> endPoints = new List<IPEndPoint>(
        new IPEndPoint[]{
            new IPEndPoint(IPAddress.Parse("127.0.0.1"), 80),
            new IPEndPoint(IPAddress.Parse("69.59.196.211"), 80),
            new IPEndPoint(IPAddress.Parse("74.125.45.100"), 80)
        });
    using (DatabaseFile dbf = new DatabaseFile("iptable.txt"))
    {
        foreach (IPEndPoint endPoint in endPoints)
            dbf.Append(new Record { 
                Address = endPoint.Address, 
                Port = endPoint.Port });

        Record stackOverflow = dbf.Locate(r => 
            Dns.GetHostEntry(r.Address)
                .HostName.Equals("stackoverflow.com")).FirstOrDefault();
        if (stackOverflow != null)
            dbf.Delete(stackOverflow);

        Record google = dbf.Locate(r =>
            r.Address.ToString() == "74.125.45.100").First();
        google.Port = 443;
        dbf.Update(google);

        foreach(Record http in dbf.Locate(r => 
            !r.Deleted && r.Port == 80))
            Console.WriteLine(http.ToString());
    }
    Console.ReadLine();
}

DBASE III ، أفتقدك.

حسنًا ، كان ذلك ممتعًا ، شكرًا لك!

تحرير 1: أضيف Pack() وكسول Sort() الشفرة؛

تحرير 2: أضيفت مفقودة IComparable/IComparer تطبيق

نصائح أخرى

أنا شخصيا سأذهب ل

192.100.10.1:500:20-21

192.100.10.2:27015-27016:80

حيث الأول هو IP وكل شيء بعد : هو منفذ ، يمكننا أيضًا تمثيل نطاق - وإذا كنا نريد أن نكون مجنونين للغاية ، فيمكننا تقديم ملف u الذي سيمثل نوع المنفذ UDP أو TCP فمثلا:

192.100.10.2:27015-27016:80:90u

و explode() سوف تعمل لصالح ما سبق بسهولة تامة.

عند الحديث عن إدخال حذف وتحديث .. يمكننا ببساطة إنشاء بنية فئة مثل

struct port{
   int portnum;
   char type;

   port(int portnum = 0, char type = 't'){
       this.portnum = portnum; this.type = type;
   }
}

class Ip{

    public:
    string Ip_str;
    list <port> prt;
}

وبعد ذلك يمكنك أن يكون لديك الرئيسي لتبدو

int main(){

    list<Ip> Ips;

    //Read the list from file and update the list.

    //Sort delete update the list

    //Rewrite the list back into file in the order mentioned obove

    return 0;
}

من المحتمل أن تكون أسهل طريقة هي إنشاء فئة صغيرة تحتوي على IP ومنفذك

class IpAddress
{
    public string IP;
    public int port;
}

ثم إنشاء ملف list<IpAddress> منهم. يمكنك بعد ذلك استخدام تسلسل XML و Deserialization للقراءة والكتابة من ملفك.

لا يقدم .NET BCL ما تبحث عنه كما تريد الاستعلام عن ملف دون تحميله في الذاكرة أولاً ودعم الإضافة/إزالة. لذلك يجب عليك إما لفة قاعدة البيانات المدمجة الخاصة بك أو يمكنك ببساطة استخدام شيء مثل SQLite http://www.sqlite.org/

IP والمنفذ هو واحد للعديد من العلاقة. سأعتبر شيئًا كهذا

t192.168.1.1 r n25 r n26 r n t192.168.1.2 r n2 r n80 r n110

حيث t عبارة

لذلك عندما تقوم بتحليل ، إذا قمت بالضغط على حرف TAB ، فأنت تعرف أن كل شيء موجود في هذا السطر من هناك إلى خط جديد هو عنوان IP ، فإن كل شيء بين الخطوط الجديدة التالية هو رقم منفذ لعنوان IP هذا حتى تضغط على علامة التبويب ، في هذه الحالة ، تكون على عنوان IP جديد. هذا بسيط وسريع ولكن ليس قابلاً للقراءة البشرية.

هذا لا علاقة له بـ IP والمنافذ .. المشكلة هي أنه ، على حد علمي ، لا تسمح Windows بإدخال أو إزالة البايتات في/من منتصف الملف ..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top