Ok I can't seem to figure this out: given the following:
IP address = 192.168.1.0
Subnetmask = 255.255.255.240
Using c#, how do I calculate the CIDR notation 192.168.1.0/28 ? Is there an easy way to achieve this? Am I missing something?
Thanks!
256 - 240 = 16 = 2**4, 32 - 4 = 28
It is not really a C# question.
To get a net address from an IP and mask you can apply bytewise and to the IP and mask. You can get bytes from a string using IPAddress.Parse() and IPAddress.GetAddressBytes().
I had to do the same thing, no new info but this snippet may come in handy for the next person looking for a way to do this in C#.
note that this method only counts the number of consecutive 1s, and leaves you the work of appending it to the IP.
public class IPAddressHelper
{
public static UInt32 SubnetToCIDR(string subnetStr)
{
IPAddress subnetAddress = IPAddress.Parse(subnetStr);
byte[] ipParts = subnetAddress.GetAddressBytes();
UInt32 subnet = 16777216 * Convert.ToUInt32(ipParts[0]) + 65536 * Convert.ToUInt32(ipParts[1]) + 256 * Convert.ToUInt32(ipParts[2]) + Convert.ToUInt32(ipParts[3]);
UInt32 mask = 0x80000000;
UInt32 subnetConsecutiveOnes = 0;
for (int i = 0; i < 32; i++)
{
if (!(mask & subnet).Equals(mask)) break;
subnetConsecutiveOnes++;
mask = mask >> 1;
}
return subnetConsecutiveOnes;
}
}
Keep it simple!
This works for IPv4 only, but since IPv6 does only support CIDR like /64 in fe80::1ff:fe23:4567:890a/64 calculations like that are unnecessary there.
All you need for an IPv4 network mask:
int cidr = Convert.ToString(mask.Address, 2).Count( o => o == '1');
Explanation based on the given example:
IPAddress mask = new IPAddress(new byte[] { 255, 255, 255, 240 });
// maskBinAsString = 11110000111101001111111111111111
string maskBinAsString = Convert.ToString(mask.Address, 2);
// cidr = 28
int cidr = Convert.ToString(mask.Address, 2).Count( o=> o == '1');
I don't have it as C# code but here is the answer in VB. Should not be to hard to convert.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim someIP As Net.IPAddress = Net.IPAddress.Parse("192.168.1.10")
Dim someMASK As Net.IPAddress = Net.IPAddress.Parse("255.255.255.240")
Dim ipL As Long = IPtoLong(someIP)
Dim maskL As Long = IPtoLong(someMASK)
'Convert Mask to CIDR(1-30)
Dim oneBit As Long = &H80000000L
Dim CIDR As Integer = 0
For x As Integer = 31 To 0 Step -1
If (maskL And oneBit) = oneBit Then CIDR += 1 Else Exit For
oneBit = oneBit >> 1
Next
Dim answer As String = LongToIp(ipL And maskL) & " /" & CIDR.ToString
End Sub
Public Function IPtoLong(ByVal theIP As Net.IPAddress) As Long 'convert IP to number
Dim IPb() As Byte = theIP.GetAddressBytes 'get the octets
Dim addr As Long 'accumulator for address
For x As Integer = 0 To 3
addr = addr Or (CLng(IPb(x)) << (3 - x) * 8)
Next
Return addr
End Function
Public Function LongToIp(ByVal theIP As Long) As String 'convert number back to IP
Dim IPb(3) As Byte '4 octets
Dim addr As String = "" 'accumulator for address
Dim mask8 As Long = MaskFromCidr(8) 'create eight bit mask
For x = 0 To 3 'get the octets
IPb(x) = CByte((theIP And mask8) >> ((3 - x) * 8))
mask8 = mask8 >> 8
addr &= IPb(x).ToString & "." 'add current octet to string
Next
Return addr.TrimEnd("."c)
End Function
Private Function MaskFromCidr(ByVal CIDR As Integer) As Long
MaskFromCidr = CLng(2 ^ ((32 - CIDR)) - 1) Xor 4294967295L
End Function
my solution, first parse to IPAddress:
var Subnetmask = "255.255.255.240";
IPAddress ip = IPAddress.Parse(Subnetmask);
then, check count of set bits in the mask ip:
var intAddress = (int)IPAddress.Address;
Console.WriteLine(NumberOfSetBits(intAddress)); //28
the function (from https://stackoverflow.com/a/12175897/1271037):
int NumberOfSetBits(int i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
I know it's a little late, but I took a swing converting dbasnett's answer VB.NET code above to C# (thanks to Telerik Code Converter) and put it up in a .NET Fiddle here and included my conversion below:
public static void Main()
{
System.Net.IPAddress someIP = System.Net.IPAddress.Parse("192.168.1.23");
System.Net.IPAddress someMASK = System.Net.IPAddress.Parse("255.255.255.128");
long ipL = IPtoLong(someIP);
long maskL = IPtoLong(someMASK);
// Convert Mask to CIDR(1-30)
long oneBit = 0x80000000L;
int CIDR = 0;
for (int x = 31; x >= 0; x += -1)
{
if ((maskL & oneBit) == oneBit)
CIDR += 1;
else
break;
oneBit = oneBit >> 1;
}
string answer = LongToIp(ipL & maskL) + "/" + CIDR.ToString();
Console.Out.WriteLine("woah woah we woah " + answer);
}
public static long IPtoLong(System.Net.IPAddress theIP) // convert IP to number
{
byte[] IPb = theIP.GetAddressBytes(); // get the octets
long addr = 0; // accumulator for address
for (int x = 0; x <= 3; x++) {
addr |= (System.Convert.ToInt64(IPb[x]) << (3 - x) * 8);
}
return addr;
}
public static string LongToIp(long theIP) // convert number back to IP
{
byte[] IPb = new byte[4]; // 4 octets
string addr = ""; // accumulator for address
long mask8 = MaskFromCidr(8); // create eight bit mask
for (var x = 0; x <= 3; x++) // get the octets
{
IPb[x] = System.Convert.ToByte((theIP & mask8) >> ((3 - x) * 8));
mask8 = mask8 >> 8;
addr += IPb[x].ToString() + "."; // add current octet to string
}
return addr.TrimEnd('.');
}
private static long MaskFromCidr(int CIDR)
{
return System.Convert.ToInt64(Math.Pow(2, ((32 - CIDR))) - 1) ^ 4294967295L;
}
See Get CIDR from netmask
Usage:
var cidrnetmask = MaskToCIDR(IPAddress.Parse("255.0.0.0").GetAddressBytes());
This works for IPv4. To support IPv6, one could expand the number of bytes but hopefully nobody will try and use old-style netmasks for IPv6 :o)
Method:
static int MaskToCIDR(byte[] bytes)
{
var b0 = bytes[0];
var b1 = bytes[1];
var b2 = bytes[2];
var b3 = bytes[3];
return
b3 != 0 ? (
(b3 & 0x01) != 0 ? 32 :
(b3 & 0x02) != 0 ? 31 :
(b3 & 0x04) != 0 ? 30 :
(b3 & 0x08) != 0 ? 29 :
(b3 & 0x10) != 0 ? 28 :
(b3 & 0x20) != 0 ? 27 :
(b3 & 0x40) != 0 ? 26 :
25 ) :
b2 != 0 ? (
(b2 & 0x01) != 0 ? 24 :
(b2 & 0x02) != 0 ? 23 :
(b2 & 0x04) != 0 ? 22 :
(b2 & 0x08) != 0 ? 21 :
(b2 & 0x10) != 0 ? 20 :
(b2 & 0x20) != 0 ? 19 :
(b2 & 0x40) != 0 ? 18 :
17 ) :
b1 != 0 ? (
(b1 & 0x01) != 0 ? 16 :
(b1 & 0x02) != 0 ? 15 :
(b1 & 0x04) != 0 ? 14 :
(b1 & 0x08) != 0 ? 13 :
(b1 & 0x10) != 0 ? 12 :
(b1 & 0x20) != 0 ? 11 :
(b1 & 0x40) != 0 ? 10 :
9 ) :
b0 != 0 ? (
(b0 & 0x01) != 0 ? 8 :
(b0 & 0x02) != 0 ? 7 :
(b0 & 0x04) != 0 ? 6 :
(b0 & 0x08) != 0 ? 5 :
(b0 & 0x10) != 0 ? 4 :
(b0 & 0x20) != 0 ? 3 :
(b0 & 0x40) != 0 ? 2 :
1 ) :
0;
}
Related
I've got four checkboxes linked to a hex value between 0x00 and 0x0F, so if you type in 0x0B which would be 1011 the check boxes would be checked, not checked, checked, checked. For this I used:
if ((controlByte.Item2 & 0x01) == 0x01)
{
control1 = true;
}
if ((controlByte.Item2 & 0x02) == 0x02)
{
control2 = true;
}
if ((controlByte.Item2 & 0x04) == 0x04)
{
control3 = true;
}
if ((controlByte.Item2 & 0x08) == 0x08)
{
control4 = true;
}
Next I want it to go the other direction, so as you click checkboxes the hex value will change.
If I have the current value 0x0B (1011) And click the first box I want it to return 0x0A (1010). My function will go over each checkbox and update the hex value as it goes. My current attempt looks like this:
if (checkbox1)
{
controlbyte = (byte)(controlbyte | 0x01);
}
else
{
controlbyte = (byte)(controlbyte ^ 0x01);
}
It looks like this toggles it, but when I run through all checkboxes it toggles ones I didn't click. Is there a better way to take 0x0B (1011) and just set one of the bits to 0 or 1?
( 1 << flag ) <--- change like this;
if ((controlByte.Item2 & (1 << flag)) == (1 << flag))
{
control[flag] = true;
}
//0x01 == 1 << 1;
//0x02 == 1 << 2;
//0x04 == 1 << 3;
//0x08 == 1 << 4;
//because it same like this:
if ((controlByte.Item2 & (1 << 1)) == (1 << 1))
{
control1 = true;
}
if ((controlByte.Item2 & (1 << 2)) == (1 << 2))
{
control2 = true;
}
if ((controlByte.Item2 & (1 << 3)) == (1 << 3))
{
control3 = true;
}
...
controlbyte = (byte)(controlbyte | (1 << 1));
controlbyte = (byte)(controlbyte ^ (1 << 1));
I have 4 byte data stream, I know at what bite I wanted to split them and assign them to a different variable. keeping in mind the data I receive is in hex format. let's say,
P_settings 4bytes p_timeout [6:0]
p_s_detected[7]
p_o_timeout [14:8]
p_o_timeout_set [15]
override_l_lvl [23:16]
l_b_lvl [31:24]
above P_settings is 4 bytes and I wanted to split them byte into bits like p_timeout [6:0] requires 7 bits of those 4 byte.
Currently, the implementation I have tried is..for just one byte split into bits.
var soch = ((b_data>> 0)& 0x7F ); if i want first 7 bits
how do I do it for 4 byte streams
Try code like this. You said input was a stream.
public class P_Settings
{
byte p_timeout; //[6:0]
Boolean p_s_detected; //[7]
byte p_o_timeout; // [14:8]
Boolean p_o_timeout_set; // [15]
byte override_l_lvl; //[23:16]
byte l_b_lvl; //[31:24]
public P_Settings(Stream data)
{
byte input = (byte)(data.ReadByte() & 0xff);
p_timeout = (byte)(input & 0x7F);
p_s_detected = (input & 0x80) == 0 ? false : true;
input = (byte)(data.ReadByte() & 0xff);
p_o_timeout = (byte)(input & 0x7F);
p_o_timeout_set = (input & 0x80) == 0 ? false : true;
override_l_lvl = (byte)(data.ReadByte() & 0xff);
l_b_lvl = (byte)(data.ReadByte() & 0xff);
}
}
SO it turns out it much easier that i thought..
1) separate them by single byte and put them in a buffer and & operate them individually and you will get the data. thanks for all the support.
**
byte input = (byte)( buffer[10]);//1 byte
var p_timeout = (byte)(input & 0x7F);
var p_s_detected = (input & 0x80) == 0 ? false : true;
input = (byte)( buffer[11]);//1 byte
var p_o_timeout = (byte)(input & 0x7F);
var p_o_timeout_set = (input & 0x80) == 0 ? false : true;
var override_l_lvl = (byte)(buffer[12] & 0xff);//1 byte
var l_b_lvl = (byte)(buffer[13] & 0xff); //1 byte
**
I have a code that turns an integer to its binary representation, but I was wondering if there is a more simple or "easier" way of doing so. I know that there is a built-in method in C# that does this for you automatically, but that is not what I want to use.
This version loops over each o the 32-bit positions while writing ones and zeros and uses TrimStart to remove leading zeroes.
For example, converting the integer 10 to its string representation in
binary as "1010".
static string IntToBinary(int n)
{
char[] b = new char[32];
int pos = 31;
int i = 0;
while (i < 32) // Loops over each of the 32-bit positions while writing ones and zeros.
{
if ((n & (1 << i)) != 0)
{
b[pos] = '1';
}
else
{
b[pos] = '0';
}
pos--;
i++;
}
return new string(b).TrimStart('0'); // TrimStart removes leading zeroes.
}
static void Main()
{
Console.WriteLine(IntToBinary(300));
}
I suppose you could use a nibble lookup table:
static string[] nibbles = {
"0000", "0001", "0010", "0011",
"0100", "0101", "0110", "0111",
"1000", "1001", "1010", "1011",
"1100", "1101", "1110", "1111"
};
public static string IntToBinary(int n)
{
return
nibbles[(n >> 28) & 0xF] +
nibbles[(n >> 24) & 0xF] +
nibbles[(n >> 20) & 0xF] +
nibbles[(n >> 16) & 0xF] +
nibbles[(n >> 12) & 0xF] +
nibbles[(n >> 8) & 0xF] +
nibbles[(n >> 4) & 0xF] +
nibbles[(n >> 0) & 0xF]
.TrimStart('0');
}
Here is a simple LINQ implementation:
static string IntToBinary(int n)
{
return string.Concat(Enumerable.Range(0, 32)
.Select(i => (n & (1 << (31 - i))) != 0 ? '1' : '0')
.SkipWhile(ch => ch == '0'));
}
Another one using for loop:
static string IntToBinary(int n)
{
var chars = new char[32];
int start = chars.Length;
for (uint bits = (uint)n; bits != 0; bits >>= 1)
chars[--start] = (char)('0' + (bits & 1));
return new string(chars, start, chars.Length - start);
}
I'm trying to compare two strings(Tx & Rx data) and find the quantity of unequal chars.
With the help of the following code, I managed to get the quantity,
string TxData = "00001111";
string RxData = "00000000";
int distorted = 0;
for (int i = 0; i < TxData.Length; i++)
{
if (TxData[i] != RxData[i])
distorted++;
}
Console.Write("Distorted Bits (qty) : {0}", distorted);
Result:
Distorted Bits (qty) : 4
But I'm very curious to know if there's any better way to do this task?
Thanks for your time...:)
If they're always the same length:
int distorted = TxData.Zip(RxData, (a,b) => a == b ? 0 : 1).Sum();
I like okrumnows answer by its simplisity, but assuming that you really already have bytes (or int) and don't need to convert them to string in the first place, you would probably be better of doing something like:
int myMethod(byte byte1, byte byte2)
{
//byte1 = Convert.ToByte("10010101",2);
//byte2 = Convert.ToByte("10011101",2);
byte xorvalue = (byte)( byte1 ^ byte2);
return NumberOfSetBits(xorvalue);
}
private static int NumberOfSetBits(uint i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
This will be much faster.
There's a similar question asked and answered in C, but I'm struggling a bit to achieve the same thing in C#.
Generator Polynomial : x^16 + x^10 + x^8 + x^7 + x^3 + 1 which is equivalent to 10000010110001001 in binary.
I have 48 bits of data, and now I required to generate 16 bits of CRC, here's the code:
private bool[] MakeCRC(string BitString)
{
bool[] Res = new bool[17];
bool[] CRC = new bool[16];
int i;
bool DoInvert= false;
for (i = 0; i < 16; ++i) // Init before calculation
CRC[i] = false;
for (i = 0; i < BitString.Length; ++i)
{
if (BitString[i] == '1')
DoInvert = true ^ CRC[15];
//DoInvert = ('1' == BitString[i]) ^ CRC[15]; // XOR required?
CRC[15] = CRC[14];
CRC[14] = CRC[13];
CRC[13] = CRC[12];
CRC[12] = CRC[11];
CRC[11] = CRC[10];
CRC[10] = CRC[9] ^ DoInvert;
CRC[9] = CRC[8];
CRC[8] = CRC[7] ^ DoInvert;
CRC[7] = CRC[6] ^ DoInvert;
CRC[6] = CRC[5];
CRC[5] = CRC[4];
CRC[4] = CRC[3];
CRC[3] = CRC[2] ^ DoInvert;
CRC[2] = CRC[1];
CRC[1] = CRC[0];
CRC[0] = DoInvert;
}
for (i = 0; i < 16; ++i)
Res[15 - i] = CRC[i] ? true : false;
Res[16] = false; // Set string terminator
return (Res);
}
but the above code, gives me wrong output, please suggest me if there's any better way of doing it.
Edit:
Data(a0 to a47): 100011100011000001000001000100001000000000001000
Polynomial: 10000010110001001
Output Obtained: 0011 0100 1111 0111
Output Expected: 1100 1101 0100 1111
Thanks for your time.!
uncomment DoInvert = ('1' == BitString[i]) ^ CRC[15];
and remove the line above and it works.
Your replacement for the commented line is wrong. Right would be:
if (BitString[i] == '1')
DoInvert = true ^ CRC[15];
else
DoInvert = false ^ CRC[15];