How can I increment an IP address by a specified amount? - c#

I am trying to figure out how to increment a starting ip address, and increment it by an offset that I specify. I have attempted to do this, but I am doing something wrong because I am getting IPs that are all over the place, not even in the same network range.
What I am currently doing is taking my starting ip and ending ip, getting the total amount of addresses then incrementing the total ips by an offset then attempting to actually increment the IP.
I am incrementing to the total ips by an offset so I know how many to increment the ip. (I am completing different tasks per offset.) Whatever the loop has incremented "t" to that is how many I increment IPs. Now that I have given the rundown, my issue only seems to be with actually incrementing ips, can anyone help me out in this situation. Thanks.
string from = txtStart.Text, to = txtEnd.Text;
uint current = from.ToUInt(), last = to.ToUInt();
ulong total = last - current;
int offset = 3; //This is an example number, it actually could be anything.
while (current <= last)
{
for (int t = 0; t < total; t += offset)
{
uint ut = Convert.ToUInt32(t);
current = current + ut;
var ip = current.ToIPAddress();
}
}
Here is the extension class I am using. They work fine.
public static class Extensions
{
public static uint ToUInt(this string ipAddress)
{
var ip = IPAddress.Parse(ipAddress);
var bytes = ip.GetAddressBytes();
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
public static string ToString(this uint ipInt)
{
return ToIPAddress(ipInt).ToString();
}
public static IPAddress ToIPAddress(this uint ipInt)
{
var bytes = BitConverter.GetBytes(ipInt);
Array.Reverse(bytes);
return new IPAddress(bytes);
}
}

[TestFixture]
public class GetNextIpAddressTest
{
[Test]
public void ShouldGetNextIp()
{
Assert.AreEqual("0.0.0.1", GetNextIpAddress("0.0.0.0", 1));
Assert.AreEqual("0.0.1.0", GetNextIpAddress("0.0.0.255", 1));
Assert.AreEqual("0.0.0.11", GetNextIpAddress("0.0.0.1", 10));
Assert.AreEqual("123.14.1.101", GetNextIpAddress("123.14.1.100", 1));
Assert.AreEqual("0.0.0.0", GetNextIpAddress("255.255.255.255", 1));
}
private static string GetNextIpAddress(string ipAddress, uint increment)
{
byte[] addressBytes = IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray();
uint ipAsUint = BitConverter.ToUInt32(addressBytes, 0);
var nextAddress = BitConverter.GetBytes(ipAsUint + increment);
return String.Join(".", nextAddress.Reverse());
}
}

An IPv4 address is basically a 32 bit Integer. Therefore you can just parse the substrings from e.g. 192.168.0.1 and convert each byte to an integer number:
uint byte1 = Converter.ToUint32("192");
and so on ..
Then you could just "OR" or "ADD" them together like this:
uint IP = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
and increment that integer with step_size as needed. Here is an example:
using System.IO;
using System;
class Program
{
static void Main()
{
String ipString = "192.168.0.1";
String[] ipBytes = ipString.Split('.');
uint byte1 = Convert.ToUInt32(ipBytes[0]);
uint byte2 = Convert.ToUInt32(ipBytes[1]);
uint byte3 = Convert.ToUInt32(ipBytes[2]);
uint byte4 = Convert.ToUInt32(ipBytes[3]);
uint IP = (byte1 << 24)
| (byte2 << 16)
| (byte3 << 8)
| byte4 ;
uint step_size = 90000000;
while( IP != 0xFFFFFFFF ) {
Console.WriteLine(
((IP >> 24) & 0xFF) + "." +
((IP >> 16) & 0xFF) + "." +
((IP >> 8 ) & 0xFF) + "." +
( IP & 0xFF)
);
// if (0xFFFFFFFF - IP) < step_size then we can't
// add step_size to IP due to integer overlow
// which means that we have generated all IPs and
// there isn't any left that equals IP + step_size
if( (0xFFFFFFFF - IP) < step_size ) {
break;
}
IP += step_size; // next ip address
}
}
}
Output
192.168.0.1
198.5.74.129
203.98.149.1
208.191.223.129
214.29.42.1
219.122.116.129
224.215.191.1
230.53.9.129
235.146.84.1
240.239.158.129
246.76.233.1
251.170.51.129

The following is a class I use for working with IP addresses which includes the ability to increment an IP address as well as to build a range of IPs.
public sealed class IPAddressTools
{
public static UInt32 ConvertIPv4AddressToUInt32(IPAddress address)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
return addressInteger;
}
public static IPAddress ConvertUInt32ToIPv4Address(UInt32 addressInteger)
{
if (addressInteger < 0 || addressInteger > 4294967295) throw new ArgumentOutOfRangeException("addressInteger", "The value of addressInteger must be between 0 and 4294967295.");
Byte[] addressBytes = new Byte[4];
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}
public static IPAddress IncrementIPAddress(IPAddress address, int offset)
{
return ModIPAddress(address, 1);
}
public static IPAddress ModIPAddress(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.");
UInt32 addressInteger = ConvertIPv4AddressToUInt32(address);
addressInteger += offset;
return ConvertUInt32ToIPv4Address(addressInteger);
}
public static IPAddress[] GetIpRange(IPAddress address, IPAddress mask)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (mask == null) throw new ArgumentNullException("mask", "The value of mask is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.");
if (mask.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified mask's family is invalid.");
byte[] addressBytes = address.GetAddressBytes();
byte[] maskBytes = mask.GetAddressBytes();
byte[] startIpBytes = new byte[addressBytes.Length];
byte[] endIpBytes = new byte[addressBytes.Length];
for (int i = 0; i < addressBytes.Length; i++)
{
startIpBytes[i] = (byte)(addressBytes[i] & maskBytes[i]);
endIpBytes[i] = (byte)(addressBytes[i] | ~maskBytes[i]);
}
IPAddress startIp = new IPAddress(startIpBytes);
IPAddress endIp = new IPAddress(endIpBytes);
List<IPAddress> addresses = new List<IPAddress>();
for (IPAddress currentIp = startIp; ConvertIPv4AddressToUInt32(currentIp) <= ConvertIPv4AddressToUInt32(endIp); currentIp = IncrementIPAddress(currentIp))
{
addresses.Add(currentIp);
}
return addresses.ToArray();
}
}
You could also implement the + and - operators for the IPAddress class, but since it wouldn't work for all uses of the class it's probably not a good idea.
public static IPAddress operator +(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
addressInteger += offset;
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}
public static IPAddress operator -(IPAddress address, int offset)
{
if (address == null) throw new ArgumentNullException("address", "The value of address is a null reference.");
if (address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork) throw new ArgumentException("The specified address's family is invalid.", "address");
Byte[] addressBytes = address.GetAddressBytes();
UInt32 addressInteger = (((UInt32)addressBytes[0]) << 24) + (((UInt32)addressBytes[1]) << 16) + (((UInt32)addressBytes[2]) << 8) + ((UInt32)addressBytes[3]);
addressInteger -= offset;
addressBytes[0] = (Byte)((addressInteger >> 24) & 0xFF);
addressBytes[1] = (Byte)((addressInteger >> 16) & 0xFF);
addressBytes[2] = (Byte)((addressInteger >> 8) & 0xFF);
addressBytes[3] = (Byte)(addressInteger & 0xFF);
return new IPAddress(addressBytes);
}

In your cycle you are doing some wild increments. First increment t is 0 so ip stays the same. Second increment t is 3 so 192.168.1.1 becomes 192.168.1.4(and you save it as current). Third increment t is 6 so 192.168.1.4 becomes 192.168.1.10(and saved as current) ...
I think what you are trying to achieve is somthing like this:
string from = "192.168.1.1", to = "192.168.1.255";
uint first = from.ToUInt(), last = to.ToUInt();
ulong total = last - first;
uint offset = 3; //This is an example number, it actually could be anything.
for (uint t = 0; (ulong)t < total; t += 1)
{
uint ut = Convert.ToUInt32(t);
uint c = first + t + offset;
var ip = c.ToIPAddress();
}

Ip can be decomposed as follow
integer value= (4thOctat*2^24.3rd*2^16.2nd*2^8.1st*2^0)
e.g. 64.233.187.99
64*2^24 + 233*2^16 + 187*2^8 + 99
= 1089059683
I wrote this small example for you,
//This is regular expression to check the the ip is in correct format
private readonly Regex ip = new Regex(#"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
private void Main()
{
string IpAddress = "172.22.1.1";
if (ip.IsMatch(IpAddress))
{
//increment first octat by 5
string IncrementedIp = IncrementIP(0, 100, IPAddress.Parse(IpAddress));
if (ip.IsMatch(IncrementedIp))
{
Console.WriteLine("Incremented Ip = {0}", IncrementedIp);
}
else
{
//not valid ip address}
}
}else
{
//Not Valid Ip Address
}
}
private string IncrementIP(short octat, long Offset,IPAddress adress)
{
//octat range from 0-3
if ( octat<0 ||octat > 3) return adress.ToString();
long IpLong = AdressToInt(adress.ToString());
IpLong += (long)(Offset*(Math.Pow(2,octat*8)));
return longToAddress(IpLong);
}
static long AdressToInt(string addr)
{
return (long)(uint)IPAddress.NetworkToHostOrder(
(int)IPAddress.Parse(addr).Address);
}
static string longToAddress(long address)
{
return IPAddress.Parse(address.ToString()).ToString();
}

To evaluate a little: You simply change the numeric representation of a value from one base to another, the another in this case being the 10-base, which your code, your head and your computer language use commonly. In 10-base, you can easily perform arithmetics. Once you have done that, you change the resulting number back to another base again, for example the original one.
In the case of an IP-address, the base is 256. As said earlier, an IP-address is simply a numeric value consisting 32 bits.
Bits are 2-base (toolset: 0,1)
Your calculation happens in 10-base (0,1,2,3,4,5,6,7,8,9)
Hexa is 16-base ((0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F)
An IP-address is (4 of) 256-base (0,1,2,3,4,5,6,7,8,9,[we should have another 246 unique symbols here]). As we do not have 256 unique numeric symbols (would be too many anyway), we describe these for convenience using 10-base instead, for example 253 (but 253 should really be the 254th symbol in a symbol table, like in the ASCII-table).
There are a million cases when you want to change base, or change numeric space. One example is incrementing a date. You change to the manageable days-since-20th-centurystart-space (the actual change isn't too simple, but the good result is a 10-base representation), perform the calculation (eg. increment with 7 days), and then change back to YMD-space.
The IP-address 255.255.255.255 could also be described using the 10-base integer value 4294967295.

They Answers are right... for addition to your implementation
CheckAgain:
If My.Computer.Network.Ping(CheckIPFirst) = False Then
'=====IF IP ADDRESS NOT OCCUPIED GET=========
CheckIPFirst +=1
GETIpAddress(Counter) = CheckIPFirst
Else
'======CHECK ANOTHER IP ADDRESS=============
CheckIPFirst +=1
Goto CheckAgain
End If
Through that you will not encounter a IP Address Conflict or Same IP Address.

Related

Problem implementing C# listener for Concox GPS tracker HVT001

I am trying to implement a C# listener for a Concox GPS tracker (model HVT001) using the code examples that are available online but for some reason I am not able to get the Terminal ID (IMEI) correctly and I can't get any location messages after the login
Below is a screen capture of the input from my console window:
As you can see the Terminal ID appears as gibberish and no location messages appear (I'm also getting protocol numbers that I don't recognize)
Any help would be appreciated.
The full code is available here: https://docs.google.com/document/d/1UsF7ocb5CsCI1rxTcJHLP2eejR6vvboD_M8UeadkVmI/edit?usp=sharing
And here is a snippet of the code:
public void ProcessMessages()
{
UInt16 sendCRC = 0;
DateTime date;
int year = 0;
int month = 0;
int day = 0;
int hour = 0;
int minute = 0;
int second = 0;
KeyValuePair<List<byte>, StateObject> byteState;
KeyValuePair<UNPACK_STATUS, byte[]> status;
byte[] receiveMessage = null;
StateObject state = null;
byte[] serialNumber = null;
byte[] serverFlagBit = null;
byte[] stringArray = null;
string stringMessage = "";
byte lengthOfCommand = 0;
PROTOCOL_NUMBER protocolNumber = PROTOCOL_NUMBER.NONE;
try
{
Boolean firstMessage = true;
acceptDone.Set();
//loop forever
while (true)
{
allDone.WaitOne();
//read fifo until empty
while (true)
{
//read one connection until buffer doesn't contain any more packets
byteState = ReadWrite(PROCESS_STATE.PROCESS, null, null, -1);
if (byteState.Value.fifoCount == -1) break;
state = byteState.Value;
while (true)
{
status = Unpack(byteState);
if (status.Key == UNPACK_STATUS.NOT_ENOUGH_BYTES)
break;
if (status.Key == UNPACK_STATUS.ERROR)
{
Console.WriteLine("Error : Bad Receive Message, Data");
break;
}
//message is 2 start bytes + 1 byte (message length) + 1 byte message length + 2 end bytes
receiveMessage = status.Value;
int messageLength = receiveMessage[2];
Console.WriteLine("Status : '{0}', Receive Message : '{1}'", status.Key == UNPACK_STATUS.GOOD_MESSAGE ? "Good" : "Bad", BytesToString(receiveMessage.Take(messageLength + 5).ToArray()));
if (status.Key != UNPACK_STATUS.GOOD_MESSAGE)
{
break;
}
else
{
if (firstMessage)
{
if (receiveMessage[3] != 0x01)
{
Console.WriteLine("Error : Expected Login Message : '{0}'", BytesToString(receiveMessage));
break;
}
firstMessage = false;
}
//skip start bytes, message length. then go back 4 bytes (CRC and serial number)
serialNumber = receiveMessage.Skip(2 + 1 + messageLength - 4).Take(2).ToArray();
protocolNumber = (PROTOCOL_NUMBER)receiveMessage[3];
Console.WriteLine("Protocol Number : '{0}'", protocolNumber.ToString());
switch (protocolNumber)
{
case PROTOCOL_NUMBER.LOGIN_MESSAGE:
serialNumber.CopyTo(loginResponse, 4);
sendCRC = crc_bytes(loginResponse.Skip(2).Take(loginResponse.Length - 6).ToArray());
loginResponse[loginResponse.Length - 4] = (byte)((sendCRC >> 8) & 0xFF);
loginResponse[loginResponse.Length - 3] = (byte)((sendCRC) & 0xFF);
string IMEI = Encoding.ASCII.GetString(receiveMessage.Skip(4).Take(messageLength - 5).ToArray());
Console.WriteLine("Received good login message from Serial Number : '{0}', Terminal ID = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), IMEI);
//byteState.Value.IMEI = IMEI;
Console.WriteLine("Send Message : '{0}'", BytesToString(loginResponse));
Send(state.workSocket, loginResponse);
WriteDBMessageLogin loginMessage = new WriteDBMessageLogin() { message = DATABASE_MESSAGE_TYPE.LOGIN, IMEI = IMEI, date = DateTime.Now };
WriteDBAsync.ReadWriteFifo(WriteDBAsync.Mode.WRITE, loginMessage);
Console.WriteLine("Wrote to database");
break;
case PROTOCOL_NUMBER.LOCATION_DATA:
year = receiveMessage[4];
month = receiveMessage[5];
day = receiveMessage[6];
hour = receiveMessage[7];
minute = receiveMessage[8];
second = receiveMessage[9];
date = new DateTime(2000 + year, month, day, hour, minute, second);
WriteDBMessageLocation locationMessage = new WriteDBMessageLocation();
locationMessage.message = DATABASE_MESSAGE_TYPE.LOCATION;
locationMessage.trackTime = date;
locationMessage.currTime = DateTime.Now;
locationMessage.lattitude = new byte[4];
Array.Copy(receiveMessage, 11, locationMessage.lattitude, 0, 4);
locationMessage.longitude = new byte[4];
Array.Copy(receiveMessage, 15, locationMessage.longitude, 0, 4);
locationMessage.speed = receiveMessage[19];
locationMessage.courseStatus = new byte[2];
Array.Copy(receiveMessage, 20, locationMessage.courseStatus, 0, 2);
locationMessage.IMEI = byteState.Value.IMEI;
WriteDBAsync.ReadWriteFifo(WriteDBAsync.Mode.WRITE, locationMessage);
Console.WriteLine("Received good location message from Serial Number '{0}', Time = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), date.ToLongDateString());
break;
case PROTOCOL_NUMBER.ALARM_DATA:
//first response
int alarmPacketLen = alarmResponse.Length - 5;
alarmResponse[2] = (byte)(alarmPacketLen & 0xFF);
serialNumber.CopyTo(alarmResponse, alarmPacketLen - 1);
sendCRC = crc_bytes(alarmResponse.Skip(2).Take(alarmPacketLen - 1).ToArray());
alarmResponse[alarmPacketLen + 1] = (byte)((sendCRC >> 8) & 0xFF);
alarmResponse[alarmPacketLen + 2] = (byte)((sendCRC) & 0xFF);
Console.WriteLine("Send Alarm Response Message : '{0}'", BytesToString(alarmResponse));
Send(state.workSocket, alarmResponse);
//second response
year = receiveMessage[4];
month = receiveMessage[5];
day = receiveMessage[6];
hour = receiveMessage[7];
minute = receiveMessage[8];
second = receiveMessage[9];
date = new DateTime(2000 + year, month, day, hour, minute, second);
Console.WriteLine("Received good alarm message from Serial Number '{0}', Time = '{1}'", "0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"), date.ToLongDateString());
int alarmDataAddressPacketLen = alarmDataAddressResponse.Length - 5;
alarmDataAddressResponse[2] = (byte)(alarmDataAddressPacketLen & 0xFF);
serialNumber.CopyTo(alarmDataAddressResponse, alarmDataAddressPacketLen - 1);
sendCRC = crc_bytes(alarmDataAddressResponse.Skip(2).Take(alarmDataAddressPacketLen - 1).ToArray());
alarmDataAddressResponse[alarmDataAddressPacketLen + 1] = (byte)((sendCRC >> 8) & 0xFF);
alarmDataAddressResponse[alarmDataAddressPacketLen + 2] = (byte)((sendCRC) & 0xFF);
Console.WriteLine("Send Alarm Data Address Message : '{0}'", BytesToString(alarmDataAddressResponse));
Send(state.workSocket, alarmDataAddressResponse);
break;
case PROTOCOL_NUMBER.STATUS_INFO:
serialNumber.CopyTo(heartbeatResponse, 4);
byte info = receiveMessage[4];
byte voltage = receiveMessage[5];
byte GSMsignalStrength = receiveMessage[6];
UInt16 alarmLanguage = (UInt16)((receiveMessage[7] << 8) | receiveMessage[8]);
ALARM alarm = (ALARM)((info >> 3) & 0x07);
sendCRC = crc_bytes(heartbeatResponse.Skip(2).Take(heartbeatResponse.Length - 6).ToArray());
heartbeatResponse[heartbeatResponse.Length - 4] = (byte)((sendCRC >> 8) & 0xFF);
heartbeatResponse[heartbeatResponse.Length - 3] = (byte)((sendCRC) & 0xFF);
Console.WriteLine("Received good status message from Serial Number : '{0}', INFO : '0x{1}{2}{3}{4}'",
"0x" + serialNumber[0].ToString("X2") + serialNumber[1].ToString("X2"),
info.ToString("X2"), voltage.ToString("X2"), GSMsignalStrength.ToString("X2"),
alarmLanguage.ToString("X4"));
Console.WriteLine("Send Message : '{0}'", BytesToString(heartbeatResponse));
Send(state.workSocket, heartbeatResponse);
switch (alarm)
{
//reset cut off alarm
case ALARM.POWER_CUT_ALARM:
int connectOilAndElectricityPacketLen = connectOilAndEletricity.Length - 5;
serialNumber.CopyTo(connectOilAndEletricity, connectOilAndElectricityPacketLen - 1);
sendCRC = crc_bytes(connectOilAndEletricity.Skip(2).Take(connectOilAndEletricity.Length - 6).ToArray());
connectOilAndEletricity[connectOilAndEletricity.Length - 4] = (byte)((sendCRC >> 8) & 0xFF);
connectOilAndEletricity[connectOilAndEletricity.Length - 3] = (byte)((sendCRC) & 0xFF);
serverFlagBit = new byte[4];
Array.Copy(connectOilAndEletricity, 5, serverFlagBit, 0, 4);
lengthOfCommand = connectOilAndEletricity[4];
stringArray = new byte[lengthOfCommand - 4]; //do not include server flag bit
Array.Copy(connectOilAndEletricity, 9, stringArray, 0, lengthOfCommand - 4);
stringMessage = Encoding.ASCII.GetString(stringArray);
Console.WriteLine("Reset Oil and Electricity, Server Flag Bit : '{0}{1}{2}{3}', Message : '{4}'",
serverFlagBit[0].ToString("X2"),
serverFlagBit[1].ToString("X2"),
serverFlagBit[2].ToString("X2"),
serverFlagBit[3].ToString("X2"),
stringMessage);
Send(state.workSocket, connectOilAndEletricity);
break;
}
break;
case PROTOCOL_NUMBER.STRING_INFO:
lengthOfCommand = receiveMessage[4];
serverFlagBit = new byte[4];
Array.Copy(receiveMessage, 5, serverFlagBit, 0, 4);
stringArray = new byte[lengthOfCommand - 4]; //do not include server flag bit
Array.Copy(receiveMessage, 9, stringArray, 0, lengthOfCommand - 4);
stringMessage = Encoding.ASCII.GetString(stringArray);
Console.WriteLine("String Message, Server Flag Bit : '{0}{1}{2}{3}', Message : '{4}'",
serverFlagBit[0].ToString("X2"),
serverFlagBit[1].ToString("X2"),
serverFlagBit[2].ToString("X2"),
serverFlagBit[3].ToString("X2"),
stringMessage);
break;
} //end switch
}// End if
} //end while
}//end while fifo > 0
allDone.Reset();
}//end while true
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
First of all, a google docs is no way to share code bear that in mind for next questions. I cant really test your code, but from what i read in the documentacion of this GPS. I can tell you that your IMEI problem is that you are not desearializing it well.
According to the documentacion the Login Message Packet has 18 bytes, and its divided this way in order
2 as start bit
1 for the length of the package
1 for the protocol number (in this case protocol 1 or 0x01)
8 for the IMEI as a example this IMEI 123456789123456 gets sent like this: 0x01
0x23 0x45 0x67 0x89 0x120x34 0x56
2 for serial information on the number
2 for error check
and 2 more for stop
Here is your line where you deserialize it:
string IMEI = Encoding.ASCII.GetString(receiveMessage.Skip(4).Take(messageLength - 5).ToArray());
To begin with there is no need to make a calculation on how many you should take, they will always be 8 so receiveMessage.Skip(4).Take(8).ToArray()
Then there is the problem with the encoding, you dont want to convert those numbers into their ascii char, you want only to take the numbers being writen as a hex string, removing the dashes that generates the method, and removing the leading zero if any exists
BitConverter.ToString(ByteArr).Replace("-","").TrimStart('0')
This is how your IMEI variable should look like:
string IMEI = BitConverter.ToString(receiveMessage.Skip(4).Take(8).ToArray()).Replace("-","").TrimStart('0');

integer to utf8 string not working c#

I'm converting UTF8 string to integer, and the other way around.
If i enter 卐 as a string, it converts to 21328.
But when I try to convert 21328 back to string I get "PS".
I tried:
int dec = Convert.ToInt32(decimal1.Text, 10);
byte[] bajti = new byte[4];
bajti[0] = (byte)(dec >> 24);
bajti[1] = (byte)(dec >> 16);
bajti[2] = (byte)(dec >> 8);
bajti[3] = (byte)dec;
znak1.Text = Encoding.UTF8.GetString(bajti);
I have also tried converting using BitConverter and got same result.
I have thought, it could be a problem with TextBox, and I tried to wrote it down in notepad, but got same result...
You can also try the following code:
// Conversion from String to Int32
string text = "§";
byte[] textBytes = Encoding.UTF8.GetBytes(text);
byte[] numberBytes = new byte[sizeof(int)];
Array.Copy(textBytes, numberBytes, textBytes.Length);
int number = BitConverter.ToInt32(numberBytes, 0);
//Conversion from Int32 to String
numberBytes = BitConverter.GetBytes(number);
text = Encoding.UTF8.GetString(numberBytes);
PS: The code will work, but some characters when converted take up less than 4 bytes in space, therefore when converted back to a string from an Int32 (4 bytes), trailing \0 may appear (which are not rendered, because they represent a null character).
Try this:
byte[] bajti = HexToBytes(hex1.Text);
char c = 'a';
if (bajti.Length == 1)
{
c = (char)bajti[0];
}
else if (bajti.Length == 2)
{
c = (char)((bajti[0] << 8) + bajti[1]);
}
else if (bajti.Length == 3)
{
c = (char)((bajti[0] << 16) + (bajti[1] << 8) + bajti[2]);
}
else if (bajti.Length == 4)
{
c = (char)((bajti[0] << 24)+(bajti[1] << 16) + (bajti[2] << 8) + bajti[3]);
}
znak1.Text = c.ToString();

How can I separate out each bit from a byte?

I'm very new to C# (and C in general for that matter) I'm getting a byte value returned from an external source that represents the states of 8 input pins on the port of an IO device so I get a value of 0-255 representing the binary pattern present on the port.
How can I strip out the individual bits and set them as bool vars, so doing something like this:
if (inputBuffer[1] == 1)
{
IO.Input0 = true;
IO.Input1 = false;
IO.Input2 = false;
IO.Input3 = false;
IO.Input4 = false;
IO.Input5 = false;
IO.Input6 = false;
IO.Input7 = false;
}
I'm probably overexplaining what I'm trying to achieve but thought this gives the best example although highly impractical, how can I better achieve this to set the variables based on a byte value of 0-255.
Use a bitwise-and (&). Assuming Input0 represents the least significant bit:
IO.Input0 = (inputBuffer & 0x01) == 0x01;
IO.Input1 = (inputBuffer & 0x02) == 0x02;
IO.Input2 = (inputBuffer & 0x04) == 0x04;
IO.Input3 = (inputBuffer & 0x08) == 0x08;
IO.Input4 = (inputBuffer & 0x10) == 0x10;
IO.Input5 = (inputBuffer & 0x20) == 0x20;
IO.Input6 = (inputBuffer & 0x40) == 0x40;
IO.Input7 = (inputBuffer & 0x80) == 0x80;
You can also implement an extension method like the following:
public static bool IsBitSet(this byte b, int bit)
{
if(bit < 0 || bit > 7)
throw new ArgumentOutOfRangeException("bit must be between 0 and 7");
byte bitToCheck = (byte)(0x01 << bit);
return (b & bitToCheck) == bitToCheck;
}
Which you could then call like:
IO.Input4 = inputBuffer.IsBitSet(4);
Use a bitmask and the &-operator to figure this out
byte b = 100;
if(b&1 == 1) { } //bit 1 is set
if(b&2 == 2) { } //bit 2 is set
if(b&4 == 4) { } //bit 3 is set
...
I think a self written class can help. Class could contain the 8 bits and the constructor takes a byte. In the constructor you can calculate the single bits.
public class myByte
{
bool Input0 = false;
bool Input1 = false;
bool Input2 = false;
bool Input3 = false;
bool Input4 = false;
bool Input5 = false;
bool Input6 = false;
bool Input7 = false;
public myByte(byte b)
{
//written by Ic.
Input0 = b & 0x01 == 0x01;
Input1 = b & 0x02 == 0x02;
Input2 = b & 0x04 == 0x04;
Input3 = b & 0x08 == 0x08;
Input4 = b & 0x10 == 0x10;
Input5 = b & 0x20 == 0x20;
Input6 = b & 0x40 == 0x40;
Input7 = b & 0x80 == 0x80;
}
... //getter setter ...
}
You can do this.
int x= inputBuffer[1];
bit1 = ((x>>7)&1==1);
bit2 = ((x>>6)&1==1);
bit3 = ((x>>5)&1==1);
bit4 = ((x>>4)&1==1);
bit5 = ((x>>3)&1==1);
bit6 = ((x>>2)&1==1);
bit7 = ((x>>1)&1==1);
bit8 = (x&1==1);
To get 1st bit from say 11101110 value you need to right shift first bt 7 times and then doing AND operation with 1 will tell you whether the value is 1 or 0 and same solution applies for other bits as well.
You can use the BitArray class.
var bitArray = new BitArray(inputBuffer);
IO.Input1 = bitArray[byteIndex * 8 + 1];
Or
var bitArray = new BitArray(new byte[] { inputBuffer[1] });
IO.Input1 = bitArray[1];
You can also iterate it as a collection of Boolean values, and perform bitwise operation on the entire collection.
It's obviously not as performant as the other options offered here (cost of allocation) but it does provide a very neat API for bit calculations.
If the data is given to you in a Byte form and that each bit has been masked, then I would leave it as it is. Converting them to another type is unnecessary, it will be an extra work for no benefit. To get the correct bit, just use the bit mask pattern
private bool GetMaskedBit(var inputBuffer , int mask)
{
return ((inputBuffer & mask) != 0);
}
This way you parse the buffer and the required bit you wanted, this will return whether the bit has been set or not.

Calculate an Internet (aka IP, aka RFC791) checksum in C#

Interestingly, I can find implementations for the Internet Checksum in almost every language except C#. Does anyone have an implementation to share?
Remember, the internet protocol specifies that:
"The checksum field is the 16 bit one's complement of the one's
complement sum of all 16 bit words in the header. For purposes of
computing the checksum, the value of the checksum field is zero."
More explanation can be found from Dr. Math.
There are some efficiency pointers available, but that's not really a large concern for me at this point.
Please include your tests! (Edit: Valid comment regarding testing someone else's code - but I am going off of the protocol and don't have test vectors of my own and would rather unit test it than put into production to see if it matches what is currently being used! ;-)
Edit: Here are some unit tests that I came up with. They test an extension method which iterates through the entire byte collection. Please comment if you find fault in the tests.
[TestMethod()]
public void InternetChecksum_SimplestValidValue_ShouldMatch()
{
IEnumerable<byte> value = new byte[1]; // should work for any-length array of zeros
ushort expected = 0xFFFF;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void InternetChecksum_ValidSingleByteExtreme_ShouldMatch()
{
IEnumerable<byte> value = new byte[]{0xFF};
ushort expected = 0xFF;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
[TestMethod()]
public void InternetChecksum_ValidMultiByteExtrema_ShouldMatch()
{
IEnumerable<byte> value = new byte[] { 0x00, 0xFF };
ushort expected = 0xFF00;
ushort actual = value.InternetChecksum();
Assert.AreEqual(expected, actual);
}
I knew I had this one stored away somewhere...
http://cyb3rspy.wordpress.com/2008/03/27/ip-header-checksum-function-in-c/
Well, I dug up an implementation from an old code base and it passes the tests I specified in the question, so here it is (as an extension method):
public static ushort InternetChecksum(this IEnumerable<byte> value)
{
byte[] buffer = value.ToArray();
int length = buffer.Length;
int i = 0;
UInt32 sum = 0;
UInt32 data = 0;
while (length > 1)
{
data = 0;
data = (UInt32)(
((UInt32)(buffer[i]) << 8)
|
((UInt32)(buffer[i + 1]) & 0xFF)
);
sum += data;
if ((sum & 0xFFFF0000) > 0)
{
sum = sum & 0xFFFF;
sum += 1;
}
i += 2;
length -= 2;
}
if (length > 0)
{
sum += (UInt32)(buffer[i] << 8);
//sum += (UInt32)(buffer[i]);
if ((sum & 0xFFFF0000) > 0)
{
sum = sum & 0xFFFF;
sum += 1;
}
}
sum = ~sum;
sum = sum & 0xFFFF;
return (UInt16)sum;
}
I have made an implementation of the IPv4 header checksum calculation, as defined in RFC 791.
Extension Methods
public static ushort GetInternetChecksum(this ReadOnlySpan<byte> bytes)
=> CalculateChecksum(bytes, ignoreHeaderChecksum: true);
public static bool IsValidChecksum(this ReadOnlySpan<byte> bytes)
// Should equal zero (valid)
=> CalculateChecksum(bytes, ignoreHeaderChecksum: false) == 0;
The Checksum Calculation
using System.Buffers.Binary;
private static ushort CalculateChecksum(ReadOnlySpan<byte> bytes, bool ignoreHeaderChecksum)
{
ushort checksum = 0;
for (int i = 0; i <= 18; i += 2)
{
// i = 0 e.g. [0..2] Version and Internal Header Length
// i = 2 e.g. [2..4] Total Length
// i = 4 e.g. [4..6] Identification
// i = 6 e.g. [6..8] Flags and Fragmentation Offset
// i = 8 e.g. [8..10] TTL and Protocol
// i = 10 e.g. [10..12] Header Checksum
// i = 12 e.g. [12..14] Source Address #1
// i = 14 e.g. [14..16] Source Address #2
// i = 16 e.g. [16..18] Destination Address #1
// i = 18 e.g. [18..20] Destination Address #2
if (ignoreHeaderChecksum && i == 10) continue;
ushort value = BinaryPrimitives.ReadUInt16BigEndian(bytes[i..(i + 2)]);
// Each time a carry occurs, we must add a 1 to the sum
if (checksum + value > ushort.MaxValue)
{
checksum++;
}
checksum += value;
}
// One’s complement
return (ushort)~checksum;
}

How to convert an IPv4 address into a integer in C#?

I'm looking for a function that will convert a standard IPv4 address into an Integer. Bonus points available for a function that will do the opposite.
Solution should be in C#.
32-bit unsigned integers are IPv4 addresses. Meanwhile, the IPAddress.Address property, while deprecated, is an Int64 that returns the unsigned 32-bit value of the IPv4 address (the catch is, it's in network byte order, so you need to swap it around).
For example, my local google.com is at 64.233.187.99. That's equivalent to:
64*2^24 + 233*2^16 + 187*2^8 + 99
= 1089059683
And indeed, http://1089059683/ works as expected (at least in Windows, tested with IE, Firefox and Chrome; doesn't work on iPhone though).
Here's a test program to show both conversions, including the network/host byte swapping:
using System;
using System.Net;
class App
{
static long ToInt(string addr)
{
// careful of sign extension: convert to uint first;
// unsigned NetworkToHostOrder ought to be provided.
return (long) (uint) IPAddress.NetworkToHostOrder(
(int) IPAddress.Parse(addr).Address);
}
static string ToAddr(long address)
{
return IPAddress.Parse(address.ToString()).ToString();
// This also works:
// return new IPAddress((uint) IPAddress.HostToNetworkOrder(
// (int) address)).ToString();
}
static void Main()
{
Console.WriteLine(ToInt("64.233.187.99"));
Console.WriteLine(ToAddr(1089059683));
}
}
Here's a pair of methods to convert from IPv4 to a correct integer and back:
public static uint ConvertFromIpAddressToInteger(string ipAddress)
{
var address = IPAddress.Parse(ipAddress);
byte[] bytes = address.GetAddressBytes();
// flip big-endian(network order) to little-endian
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return BitConverter.ToUInt32(bytes, 0);
}
public static string ConvertFromIntegerToIpAddress(uint ipAddress)
{
byte[] bytes = BitConverter.GetBytes(ipAddress);
// flip little-endian to big-endian(network order)
if (BitConverter.IsLittleEndian)
{
Array.Reverse(bytes);
}
return new IPAddress(bytes).ToString();
}
Example
ConvertFromIpAddressToInteger("255.255.255.254"); // 4294967294
ConvertFromIntegerToIpAddress(4294967294); // 255.255.255.254
Explanation
IP addresses are in network order (big-endian), while ints are little-endian on Windows, so to get a correct value, you must reverse the bytes before converting on a little-endian system.
Also, even for IPv4, an int can't hold addresses bigger than 127.255.255.255, e.g. the broadcast address (255.255.255.255), so use a uint.
#Barry Kelly and #Andrew Hare, actually, I don't think multiplying is the most clear way to do this (alltough correct).
An Int32 "formatted" IP address can be seen as the following structure
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct IPv4Address
{
public Byte A;
public Byte B;
public Byte C;
public Byte D;
}
// to actually cast it from or to an int32 I think you
// need to reverse the fields due to little endian
So to convert the ip address 64.233.187.99 you could do:
(64 = 0x40) << 24 == 0x40000000
(233 = 0xE9) << 16 == 0x00E90000
(187 = 0xBB) << 8 == 0x0000BB00
(99 = 0x63) == 0x00000063
---------- =|
0x40E9BB63
so you could add them up using + or you could binairy or them together. Resulting in 0x40E9BB63 which is 1089059683. (In my opinion looking in hex it's much easier to see the bytes)
So you could write the function as:
int ipToInt(int first, int second,
int third, int fourth)
{
return (first << 24) | (second << 16) | (third << 8) | (fourth);
}
Try this ones:
private int IpToInt32(string ipAddress)
{
return BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes().Reverse().ToArray(), 0);
}
private string Int32ToIp(int ipAddress)
{
return new IPAddress(BitConverter.GetBytes(ipAddress).Reverse().ToArray()).ToString();
}
As noone posted the code that uses BitConverter and actually checks the endianness, here goes:
byte[] ip = address.Split('.').Select(s => Byte.Parse(s)).ToArray();
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
int num = BitConverter.ToInt32(ip, 0);
and back:
byte[] ip = BitConverter.GetBytes(num);
if (BitConverter.IsLittleEndian) {
Array.Reverse(ip);
}
string address = String.Join(".", ip.Select(n => n.ToString()));
I have encountered some problems with the described solutions, when facing IP Adresses with a very large value.
The result would be, that the byte[0] * 16777216 thingy would overflow and become a negative int value.
what fixed it for me, is the a simple type casting operation.
public static long ConvertIPToLong(string ipAddress)
{
System.Net.IPAddress ip;
if (System.Net.IPAddress.TryParse(ipAddress, out ip))
{
byte[] bytes = ip.GetAddressBytes();
return
16777216L * bytes[0] +
65536 * bytes[1] +
256 * bytes[2] +
bytes[3]
;
}
else
return 0;
}
The reverse of Davy Landman's function
string IntToIp(int d)
{
int v1 = d & 0xff;
int v2 = (d >> 8) & 0xff;
int v3 = (d >> 16) & 0xff;
int v4 = (d >> 24);
return v4 + "." + v3 + "." + v2 + "." + v1;
}
With the UInt32 in the proper little-endian format, here are two simple conversion functions:
public uint GetIpAsUInt32(string ipString)
{
IPAddress address = IPAddress.Parse(ipString);
byte[] ipBytes = address.GetAddressBytes();
Array.Reverse(ipBytes);
return BitConverter.ToUInt32(ipBytes, 0);
}
public string GetIpAsString(uint ipVal)
{
byte[] ipBytes = BitConverter.GetBytes(ipVal);
Array.Reverse(ipBytes);
return new IPAddress(ipBytes).ToString();
}
My question was closed, I have no idea why . The accepted answer here is not the same as what I need.
This gives me the correct integer value for an IP..
public double IPAddressToNumber(string IPaddress)
{
int i;
string [] arrDec;
double num = 0;
if (IPaddress == "")
{
return 0;
}
else
{
arrDec = IPaddress.Split('.');
for(i = arrDec.Length - 1; i >= 0 ; i = i -1)
{
num += ((int.Parse(arrDec[i])%256) * Math.Pow(256 ,(3 - i )));
}
return num;
}
}
Assembled several of the above answers into an extension method that handles the Endianness of the machine and handles IPv4 addresses that were mapped to IPv6.
public static class IPAddressExtensions
{
/// <summary>
/// Converts IPv4 and IPv4 mapped to IPv6 addresses to an unsigned integer.
/// </summary>
/// <param name="address">The address to conver</param>
/// <returns>An unsigned integer that represents an IPv4 address.</returns>
public static uint ToUint(this IPAddress address)
{
if (address.AddressFamily == AddressFamily.InterNetwork || address.IsIPv4MappedToIPv6)
{
var bytes = address.GetAddressBytes();
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
return BitConverter.ToUInt32(bytes, 0);
}
throw new ArgumentOutOfRangeException("address", "Address must be IPv4 or IPv4 mapped to IPv6");
}
}
Unit tests:
[TestClass]
public class IPAddressExtensionsTests
{
[TestMethod]
public void SimpleIp1()
{
var ip = IPAddress.Parse("0.0.0.15");
uint expected = GetExpected(0, 0, 0, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIp2()
{
var ip = IPAddress.Parse("0.0.1.15");
uint expected = GetExpected(0, 0, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIpSix1()
{
var ip = IPAddress.Parse("0.0.0.15").MapToIPv6();
uint expected = GetExpected(0, 0, 0, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void SimpleIpSix2()
{
var ip = IPAddress.Parse("0.0.1.15").MapToIPv6();
uint expected = GetExpected(0, 0, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
[TestMethod]
public void HighBits()
{
var ip = IPAddress.Parse("200.12.1.15").MapToIPv6();
uint expected = GetExpected(200, 12, 1, 15);
Assert.AreEqual(expected, ip.ToUint());
}
uint GetExpected(uint a, uint b, uint c, uint d)
{
return
(a * 256u * 256u * 256u) +
(b * 256u * 256u) +
(c * 256u) +
(d);
}
}
public static Int32 getLongIPAddress(string ipAddress)
{
return IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(ipAddress).GetAddressBytes(), 0));
}
The above example would be the way I go.. Only thing you might have to do is convert to a UInt32 for display purposes, or string purposes including using it as a long address in string form.
Which is what is needed when using the IPAddress.Parse(String) function. Sigh.
If you were interested in the function not just the answer here is how it is done:
int ipToInt(int first, int second,
int third, int fourth)
{
return Convert.ToInt32((first * Math.Pow(256, 3))
+ (second * Math.Pow(256, 2)) + (third * 256) + fourth);
}
with first through fourth being the segments of the IPv4 address.
public bool TryParseIPv4Address(string value, out uint result)
{
IPAddress ipAddress;
if (!IPAddress.TryParse(value, out ipAddress) ||
(ipAddress.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork))
{
result = 0;
return false;
}
result = BitConverter.ToUInt32(ipAddress.GetAddressBytes().Reverse().ToArray(), 0);
return true;
}
Multiply all the parts of the IP number by powers of 256 (256x256x256, 256x256, 256 and 1. For example:
IPv4 address : 127.0.0.1
32 bit number:
= (127x256^3) + (0x256^2) + (0x256^1) + 1
= 2130706433
here's a solution that I worked out today (should've googled first!):
private static string IpToDecimal2(string ipAddress)
{
// need a shift counter
int shift = 3;
// loop through the octets and compute the decimal version
var octets = ipAddress.Split('.').Select(p => long.Parse(p));
return octets.Aggregate(0L, (total, octet) => (total + (octet << (shift-- * 8)))).ToString();
}
i'm using LINQ, lambda and some of the extensions on generics, so while it produces the same result it uses some of the new language features and you can do it in three lines of code.
i have the explanation on my blog if you're interested.
cheers,
-jc
I think this is wrong: "65536" ==> 0.0.255.255"
Should be: "65535" ==> 0.0.255.255" or "65536" ==> 0.1.0.0"
#Davy Ladman your solution with shift are corrent but only for ip starting with number less or equal 99, infact first octect must be cast up to long.
Anyway convert back with long type is quite difficult because store 64 bit (not 32 for Ip) and fill 4 bytes with zeroes
static uint ToInt(string addr)
{
return BitConverter.ToUInt32(IPAddress.Parse(addr).GetAddressBytes(), 0);
}
static string ToAddr(uint address)
{
return new IPAddress(address).ToString();
}
Enjoy!
Massimo
Assuming you have an IP Address in string format (eg. 254.254.254.254)
string[] vals = inVal.Split('.');
uint output = 0;
for (byte i = 0; i < vals.Length; i++) output += (uint)(byte.Parse(vals[i]) << 8 * (vals.GetUpperBound(0) - i));
var address = IPAddress.Parse("10.0.11.174").GetAddressBytes();
long m_Address = ((address[3] << 24 | address[2] << 16 | address[1] << 8 | address[0]) & 0x0FFFFFFFF);
I use this:
public static uint IpToUInt32(string ip)
{
if (!IPAddress.TryParse(ip, out IPAddress address)) return 0;
return BitConverter.ToUInt32(address.GetAddressBytes(), 0);
}
public static string UInt32ToIp(uint address)
{
return new IPAddress(address).ToString();
}
Take a look at some of the crazy parsing examples in .Net's IPAddress.Parse:
(MSDN)
"65536" ==> 0.0.255.255
"20.2" ==> 20.0.0.2
"20.65535" ==> 20.0.255.255
"128.1.2" ==> 128.1.0.2
I noticed that System.Net.IPAddress have Address property (System.Int64) and constructor, which also accept Int64 data type. So you can use this to convert IP address to/from numeric (although not Int32, but Int64) format.

Categories

Resources