C# byte [ ] operations - shall I use ArrayPool or MemoryPool? - sockets

I am writing a server application. It accepts thousands of incoming socket connections, each sending and receiving messages.
Every time a message is received or sent over the socket, I used to allocate new byte[] buffers, then they are garbage collected:
byte[] receivingBuffer = new byte[bufferSize];
To improve the performance, I want to reuse the byte[] buffers. Shall I use ArrayPool or MemoryPool?
Or shall I create an ObjectPool of fixed-length byte[] buffers? For example, if the messages I send and receive never exceed 100 KB, then I create an ObjectPool of 100 KB byte[] buffers. Every time I need to send or receive a message, I get one of these buffers.

Did some research and testing. ArrayPool is the right thing to use and will dramatically increase performance.
class Program
{
private static ManualResetEvent m_event = new ManualResetEvent(false);
private static DateTime m_dtStart;
private static int m_iNumOfIterations = 0;
private static int m_iNumOfExceptions = 0;
private static double m_dAvgSizeRatio = 0;
private static object m_lock = new object();
private static void ReportSizeRatio(double dRatio)
{
lock (m_lock)
{
m_dAvgSizeRatio = (m_dAvgSizeRatio * m_iNumOfIterations + dRatio) / (m_iNumOfIterations + 1);
m_iNumOfIterations++;
}
}
/// <summary>
/// When using ArrayPool:
/// - CPU: 1 ~ 1.5%
/// - Memory: 67 MB
/// - Speed: 9130 runs/sec
/// - Given buffer is 1.56 times bigger than asked for.
///
/// When NOT using ArrayPool:
/// - CPU: 20 ~ 25%
/// - Memory: 500 ~ 1000 MB
/// - Speed: 5300 runs/sec
///
/// Conclusion: huge improvement in performance.
/// </summary>
/// <param name="obj"></param>
private static void Test(object obj)
{
TrueRandom random = new TrueRandom(500, 800);
m_event.WaitOne();
while (true)
{
int iDesiredSize = random.GetRandomInteger() * 1000;
byte[] buffer = null;
try
{
//buffer = ArrayPool<byte>.Shared.Rent(iDesiredSize);
buffer = new byte[iDesiredSize];
ReportSizeRatio((double)buffer.Length / (double)iDesiredSize);
}
catch
{
Interlocked.Increment(ref m_iNumOfExceptions);
}
Thread.Sleep(100);
//ArrayPool<byte>.Shared.Return(buffer);
}
}
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Thread thread = new Thread(Test);
thread.Start();
}
Console.WriteLine("All threads fired.");
m_dtStart = DateTime.Now;
m_event.Set();
while (true)
{
Thread.Sleep(1000);
Console.Clear();
Console.WriteLine($"Iterations/sec: { (int)(m_iNumOfIterations / (DateTime.Now - m_dtStart).TotalSeconds) }, Ave rented size: { (m_dAvgSizeRatio * 100d).ToString("0.0") }%, exceptions: { m_iNumOfExceptions }.");
}
}
}

Related

How to store System.currentTimeMillis() in an array with a park time simulator

I'm trying to store the time in milliseconds for every time this time park is executed. And then I would like to use HdrHistogram to represent the latency.
However, i can't store the times in my array. Please, could you provide any help?
public class PracticeLatency1
{
public static void main(String [] args)
{
int[] startTimes;
long startTime;
int index=0;
startTimes = new int[10000];
startTime = System.currentTimeMillis();
runCalculations();
startTimes[index++] = (int) (System.currentTimeMillis() - startTime);
System.out.println(startTimes);
}
/**
* Run the practice calculations
*/
// System.currentTimeMillis()
private static void runCalculations()
{
// Create a random park time simulator
BaseSyncOpSimulator syncOpSimulator = new SyncOpSimulRndPark(TimeUnit.NANOSECONDS.toNanos(100),
TimeUnit.MICROSECONDS.toNanos(100));
// Execute the operation lot of times
for(int i = 0; i < 10000; i++)
{
syncOpSimulator.executeOp();
}
// TODO Show the percentile distribution of the latency calculation of each executeOp call
}
}

Unity timer count down not working when app killed android

I'm new to unity and c#, I have a code to increase energy after 10m, I have used PlayerPrefs to do so it is working in unity but not working on mobile please help.
I'm unable to understand what exactly is causing problem in phone. Also the timer pauses when the app is not killed but just minimized on mobile. I want the timer countdown to keep going game minimized and also if killed.
using System;
using UnityEngine;
using UnityEngine.UI;
public class EnergyAdder : MonoBehaviour
{
// Start is called before the first frame update
public float waitTime = 600;
Timer timer;
public GameRoot gameRoot;
public int count;
DateTime currentDate;
DateTime oldDate;
void Start()
{
//timer = new Timer(waitTime);
float remainingTime = PlayerPrefs.GetFloat("TimeOnExit");
timer = new Timer(remainingTime);
if (PlayerPrefs.HasKey("sysString"))
{
currentDate = DateTime.Now;
long temp = Convert.ToInt64(PlayerPrefs.GetString("sysString"));
oldDate = DateTime.FromBinary(temp);
TimeSpan difference = currentDate.Subtract(oldDate);
count = (int)(difference.TotalSeconds / waitTime);
Debug.Log("time remaining " + count);
gameRoot.AddEnergy(count);
timer = new Timer(remainingTime - (float)difference.TotalSeconds);
//PlayerPrefs.DeleteKey("TimeOnExit");
//PlayerPrefs.DeleteKey("sysString");
}
}
// Update is called once per frame
void Update()
{
if (Gameroot.isFull)
{
GetComponent<Text>().text = "Full";
count = 0;
timer.refresh();
}
else
{
//Debug.Log("deltatime ************************"+ secondstime);
timer.countDown();
if (timer.isFinished())
{
timer = new Timer(waitTime);
timer.refresh();
gameRoot.AddEnergy(1);
}
UpdateClock();
}
}
void UpdateClock()
{
int seconds = ((int)timer.timeLeft) % 60;
int minutes = (int)(timer.timeLeft / 60);
GetComponent<Text>().text = minutes.ToString() + ":" + seconds.ToString("00");
}
void OnApplicationQuit()
{
PlayerPrefs.SetFloat("TimeOnExit", timer.timeLeft);
var today = DateTime.Now;
PlayerPrefs.SetString("sysString", today.ToBinary().ToString());
PlayerPrefs.Save();
}
}
Please help what is wrong in above code or what is missing.
From OnApplicationQuit
Note: iOS applications are usually suspended and do not quit. You should tick "Exit on Suspend" in Player settings for iOS builds to cause the game to quit and not suspend, otherwise you may not see this call. If "Exit on Suspend" is not ticked then you will see calls to OnApplicationPause instead.
I suspect it is just the same with modern Android where your app is also not really closed but hibernate.
So I think you could use OnApplicationPause and OnApplicationFocus
On Android, when the on-screen keyboard is enabled, it causes a OnApplicationFocus(false) event. Additionally, if you press "Home" at the moment the keyboard is enabled, the OnApplicationFocus() event is not called, but OnApplicationPause() is called instead.
and just do the same as you do in OnApplicationQuit also for OnApplicationPause(true) and OnApplicationFocus(false)
and do the same as you do in Start also in OnApplicationPause(false) and OnApplictionFocus(true) like
public class EnergyAdder : MonoBehaviour
{
public float waitTime = 600;
public GameRoot gameRoot;
public int count;
// already reference this in the Inspector
[SerializeField] private Text timerText;
private Timer timer;
private DateTime currentDate;
private DateTime oldDate;
private void Awake()
{
// store this reference ONCE
if(!timerText) timerText = GetComponent<Text>();
}
private void Start()
{
GetTime();
}
private void Update()
{
// Note: probably a typo? shouldn't it be "gameRoot" ?
if (Gameroot.isFull)
{
timerText.text = "Full";
count = 0;
timer.refresh();
}
else
{
//Debug.Log("deltatime ************************"+ secondstime);
timer.countDown();
if (timer.isFinished())
{
timer = new Timer(waitTime);
timer.refresh();
gameRoot.AddEnergy(1);
}
UpdateClock();
}
}
private void UpdateClock()
{
int seconds = ((int)timer.timeLeft) % 60;
int minutes = (int)(timer.timeLeft / 60);
timerText.text = $"{minutes}:{seconds:00}";
}
private void OnApplicationQuit()
{
StoreTime();
}
// pauseStatus is True if the application is paused, else False.
private void OnApplicationPause(bool pauseStatus)
{
if(pauseStatus)
{
StoreTime();
}
else
{
GetTime();
}
}
// hasFocus is True if the GameObjects have focus, else False.
private void OnApplicationFocus(bool hasFocus)
{
if(hasFocus)
{
GetTime();
}
else
{
StoreTime();
}
}
private void StoreTime()
{
PlayerPrefs.SetFloat("TimeOnExit", timer.timeLeft);
var today = DateTime.Now;
PlayerPrefs.SetString("sysString", today.ToBinary().ToString());
PlayerPrefs.Save();
}
private void GetTime()
{
// NOTE: You should consider to pass a default value like
//float remainingTime = PlayerPrefs.GetFloat("TimeOnExit", 15);
float remainingTime = PlayerPrefs.GetFloat("TimeOnExit");
timer = new Timer(remainingTime);
if (PlayerPrefs.HasKey("sysString"))
{
currentDate = DateTime.Now;
long temp = Convert.ToInt64(PlayerPrefs.GetString("sysString"));
oldDate = DateTime.FromBinary(temp);
TimeSpan difference = currentDate.Subtract(oldDate);
count = (int)(difference.TotalSeconds / waitTime);
Debug.Log("time remaining " + count);
gameRoot.AddEnergy(count);
timer = new Timer(remainingTime - (float)difference.TotalSeconds);
}
}
}
Note: Typed on smartphone so I can't test it but I hope it goes into the right direction

SharedPreferences in public class - can't find value

I've been struggling to find the solution to loading some SharedPreferences values into SensorEventListener. I keep on getting blank values, null or it just crashes from example code that I found on Stackoverflow.
Here are a few of my references:
Android - How to use SharedPreferences in non-Activity class?
Android: Using SharedPreferences in a Shake Listener Class
Here is the Shake Detection code from below:
Android: I want to shake it
I'm getting these values not from a different activity, and I'd like to load them from SharedPreferences into the public class ShakeEventListener and change the static values for MIN_FORCE, MIN_DIRECTION_CHANGE and MAX_TOTAL_DURATION_OF_SHAKE to the SharedPreferences values based on the stored values.
Example of my SharedPerferences code from Motion.java:
SharedPerferences for value: MIN_FORCE
SharedPreferences spa = getSharedPreferences("ForceStore", Activity.MODE_PRIVATE);
int ValueForce = spa.getInt("Force", 15);
SharedPerferences for value: MIN_DIRECTION_CHANGE
SharedPreferences spb = getSharedPreferences("DirectionStore", MODE_PRIVATE);
int ValueDirection = spb.getInt("Direction", 2);
SharedPerferences for value: MAX_TOTAL_DURATION_OF_SHAKE
SharedPreferences spc = getSharedPreferences("ShakeStore", MODE_PRIVATE);
int ValueShake = spc.getInt("Shake", 200);
Example code from MainActivity.java:
((ShakeEventListener) mSensorListener).setOnShakeListener(new ShakeEventListener.OnShakeListener() {
public void onShake() {
// My code here to react to the Motion detected
}
}
});
}
Example code of public class ShakeEventListener:
public class ShakeEventListener implements SensorEventListener {
private static final int MIN_FORCE = 15;
private static final int MIN_DIRECTION_CHANGE = 2;
/** Maximum pause between movements. */
private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;
/** Maximum allowed time for shake gesture. */
private static final int MAX_TOTAL_DURATION_OF_SHAKE = 200;
/** Time when the gesture started. */
private long mFirstDirectionChangeTime = 0;
/** Time when the last movement started. */
private long mLastDirectionChangeTime;
/** How many movements are considered so far. */
private int mDirectionChangeCount = 0;
/** The last x position. */
private float lastX = 0;
/** The last y position. */
private float lastY = 0;
/** The last z position. */
private float lastZ = 0;
/** OnShakeListener that is called when shake is detected. */
private OnShakeListener mShakeListener;
public interface OnShakeListener {
void onShake();
}
public void setOnShakeListener(OnShakeListener listener) {
mShakeListener = listener;
}
#Override
public void onSensorChanged(SensorEvent se) {
// get sensor data
//float x = se.values[0];
//float y = se.values[1];
float z = se.values[2];
// calculate movement
//float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
float totalMovement = Math.abs(z - lastZ);
if (totalMovement > MIN_FORCE) {
// get time
long now = System.currentTimeMillis();
// store first movement time
if (mFirstDirectionChangeTime == 0) {
mFirstDirectionChangeTime = now;
mLastDirectionChangeTime = now;
}
// check if the last movement was not long ago
long lastChangeWasAgo = now - mLastDirectionChangeTime;
if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE) {
// store movement data
mLastDirectionChangeTime = now;
mDirectionChangeCount++;
// store last sensor data
//lastX = x;
//lastY = y;
lastZ = z;
// check how many movements are so far
if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE) {
// check total duration
long totalDuration = now - mFirstDirectionChangeTime;
if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) {
mShakeListener.onShake();
resetShakeParameters();
}
}
} else {
resetShakeParameters();
}
}
}
private void resetShakeParameters() {
mFirstDirectionChangeTime = 0;
mDirectionChangeCount = 0;
mLastDirectionChangeTime = 0;
// lastX = 0;
// lastY = 0;
lastZ = 0;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}

Socket Low Transfer Speed - Win7 .Net4 - CentOSx64 Mono 2.10

I have created a simple client/server app and it works great (1MB/s which is max speed i set for server to send) when i run in locally or under Lan network. But when i try to run it in one of my Dedicate Server/VPS my download speed become slow.
I am using CentOS on servers and Mono for running it, Mono version is 2.10.2 and CentOs is 64bit version. Created using framework 4.
Speed test:
Local: 1MB
Lan: 1MB
Running server on CentOS: 0~10~20 KB
My connection speed is 2Mb or ~250KB. It will give me full speed some times. But very rare and i cant see why it give my full speed sometimes and sometimes no speed at all or why sometimes only 10KB and other times only 20KB. Also, i am running client part on my Win7 Desktop. Here is code for server and client part:
Server:
class Program
{
private static BackgroundWorker _ListeningWorker;
private static BackgroundWorker _QWorker;
private static System.Net.Sockets.Socket _Server;
private static List<System.Net.Sockets.Socket> ConnectedClients = new List<System.Net.Sockets.Socket>();
static void Main(string[] args)
{
Program._ListeningWorker = new BackgroundWorker();
Program._ListeningWorker.WorkerSupportsCancellation = true;
Program._ListeningWorker.DoWork += _ListeningWorker_DoWork;
Program._QWorker = new BackgroundWorker();
Program._QWorker.WorkerSupportsCancellation = true;
Program._QWorker.DoWork += _QWorker_DoWork;
Program.Start();
while (true)
{
Console.Clear();
Console.WriteLine("1.0.0.1");
Console.WriteLine(Program.ConnectedClients.Count.ToString());
System.Threading.Thread.Sleep(1000);
}
}
public static bool Start()
{
if (!Program._ListeningWorker.IsBusy)
{
Program._Server = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, 8081);
Program._Server.Bind(ipLocal);
Program._Server.Listen(10);
Program._ListeningWorker.RunWorkerAsync();
Program._QWorker.RunWorkerAsync();
}
return true;
}
private static void _ListeningWorker_DoWork(object sender, DoWorkEventArgs e)
{
while (!Program._ListeningWorker.CancellationPending)
{
if (Program._Server.Poll(10, SelectMode.SelectRead))
{
lock (ConnectedClients)
{
Program.ConnectedClients.Add(Program._Server.Accept());
}
}
System.Threading.Thread.Sleep(1);
}
Program._Server.Close();
}
private static void _QWorker_DoWork(object sender, DoWorkEventArgs e)
{
byte[] array = new byte[1024];
Random random = new Random();
while (!Program._QWorker.CancellationPending)
{
if (ConnectedClients.Count > 0)
{
System.Net.Sockets.Socket[] st;
lock (ConnectedClients)
{
st = new System.Net.Sockets.Socket[Program.ConnectedClients.Count];
ConnectedClients.CopyTo(st);
}
foreach (System.Net.Sockets.Socket ser in st)
{
random.NextBytes(array);
try
{
ser.BeginSend(array, 0, array.Length, SocketFlags.None, (AsyncCallback)delegate(IAsyncResult ar)
{
try
{
ser.EndSend(ar);
}
catch (Exception)
{
iDissconnected(ser);
}
}, null);
}
catch (Exception)
{
iDissconnected(ser);
}
}
}
System.Threading.Thread.Sleep(1);
}
Program._Server.Close();
}
internal static void iDissconnected(System.Net.Sockets.Socket client)
{
lock (ConnectedClients)
for (int i = 0; i < ConnectedClients.Count; i++)
if (ConnectedClients[i].Equals(client))
{
ConnectedClients.RemoveAt(i);
i--;
}
}
}
Client:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter IP Address: ");
string Address = Console.ReadLine();
Console.WriteLine();
ushort Port = 8081;
System.Net.Sockets.Socket Client;
Client = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Client.Connect(Address, (int)Port);
Console.WriteLine("Connected");
int p = 0;
int t = Environment.TickCount;
while (true)
{
if (Client.Available > 0)
{
byte[] z = new byte[1024];
int r = Client.Receive(z); ;
p += r;
}
else
{
System.Threading.Thread.Sleep(10);
}
if (Environment.TickCount - t >= 1000)
{
t = Environment.TickCount;
Console.WriteLine(Program.FormatFileSizeAsString(p) + " Readed,");
p = 0;
}
}
}
public static string FormatFileSizeAsString(int len)
{
if (len < 750 && len > 0)
return "0.0 B ~";
string[] Suffix = { "B", "KB", "MB", "GB", "TB" };
int i;
double dblSByte = len;
for (i = 0; (int)(len / 1024) > 0; i++, len /= 1024)
dblSByte = len / 1024.0;
return String.Format("{0:0.0} {1}", dblSByte, Suffix[i]);
}
}
Thanks all, Please tell me what you think about possible problems.
It was some sort of limitation by ISP per each connection.
Solving was funny. I used to send a HTTP Header before my request and ISP increased my speed because of that.

How to close a TCP connection by port?

I would like to close an existing connection between to application running on my server.
If you have a suggestion please reply on how to program this, you will be appreciated.
Note that: TCPView application can close the connection exactly as I need, but I would like to run it as a console application or other command line.
Finally I found the solution for my request.
Credit goes to CSharpFriends.com, now migrated to debugging.com.
The following windows API should be used:
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
namespace ConnectionManager
{
class Disconnector
{
}
public class Starter
{
public static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine("Disconnect IP1 [IP2 [IP3 [IPn]]]");
Console.WriteLine("");
Console.WriteLine("Connections up now:");
string[] cons = Disconnecter.Connections(Disconnecter.State.Established);
foreach (string s in cons)
{
Console.WriteLine(s);
}
}
else
{
foreach (string s in args)
{
Disconnecter.CloseLocalIP(s);
Disconnecter.CloseRemoteIP(s);
}
}
}
}
public class Disconnecter
{
/// <summary>
/// Enumeration of the states
/// </summary>
public enum State
{
/// <summary> All </summary>
All = 0,
/// <summary> Closed </summary>
Closed = 1,
/// <summary> Listen </summary>
Listen = 2,
/// <summary> Syn_Sent </summary>
Syn_Sent = 3,
/// <summary> Syn_Rcvd </summary>
Syn_Rcvd = 4,
/// <summary> Established </summary>
Established = 5,
/// <summary> Fin_Wait1 </summary>
Fin_Wait1 = 6,
/// <summary> Fin_Wait2 </summary>
Fin_Wait2 = 7,
/// <summary> Close_Wait </summary>
Close_Wait = 8,
/// <summary> Closing </summary>
Closing = 9,
/// <summary> Last_Ack </summary>
Last_Ack = 10,
/// <summary> Time_Wait </summary>
Time_Wait = 11,
/// <summary> Delete_TCB </summary>
Delete_TCB = 12
}
/// <summary>
/// Connection info
/// </summary>
private struct MIB_TCPROW
{
public int dwState;
public int dwLocalAddr;
public int dwLocalPort;
public int dwRemoteAddr;
public int dwRemotePort;
}
//API to get list of connections
[DllImport("iphlpapi.dll")]
private static extern int GetTcpTable(IntPtr pTcpTable, ref int pdwSize, bool bOrder);
//API to change status of connection
[DllImport("iphlpapi.dll")]
//private static extern int SetTcpEntry(MIB_TCPROW tcprow);
private static extern int SetTcpEntry(IntPtr pTcprow);
//Convert 16-bit value from network to host byte order
[DllImport("wsock32.dll")]
private static extern int ntohs(int netshort);
//Convert 16-bit value back again
[DllImport("wsock32.dll")]
private static extern int htons(int netshort);
/// <summary>
/// Testexample
/// </summary>
public static void TEST()
{
Console.WriteLine("Not Working Yet!!!");
//string[] ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
//System.Diagnostics.Debug.WriteLine("----------------------------");
//CloseRemotePort(1863);
//CloseRemotePort(80);
//ret = Connections(State.All);
//foreach (string con in ret) if (con.IndexOf("192.168.0.101") > -1) System.Diagnostics.Debug.WriteLine(con);
}
/// <summary>
/// Close all connection to the remote IP
/// </summary>
/// <param name="IP">IPen på remote PC</param>
public static void CloseRemoteIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwRemoteAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close all connections at current local IP
/// </summary>
/// <param name="IP"></param>
public static void CloseLocalIP(string IP)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (rows[i].dwLocalAddr == IPStringToInt(IP))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the remote port
/// </summary>
/// <param name="port"></param>
public static void CloseRemotePort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwRemotePort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Closes all connections to the local port
/// </summary>
/// <param name="port"></param>
public static void CloseLocalPort(int port)
{
MIB_TCPROW[] rows = getTcpTable();
for (int i = 0; i < rows.Length; i++)
{
if (port == ntohs(rows[i].dwLocalPort))
{
rows[i].dwState = (int)State.Delete_TCB;
IntPtr ptr = GetPtrToNewObject(rows[i]);
int ret = SetTcpEntry(ptr);
}
}
}
/// <summary>
/// Close a connection by returning the connectionstring
/// </summary>
/// <param name="connectionstring"></param>
public static void CloseConnection(string connectionstring)
{
try
{
//Split the string to its subparts
string[] parts = connectionstring.Split('-');
if (parts.Length != 4) throw new Exception("Invalid connectionstring - use the one provided by Connections.");
string[] loc = parts[0].Split(':');
string[] rem = parts[1].Split(':');
string[] locaddr = loc[0].Split('.');
string[] remaddr = rem[0].Split('.');
//Fill structure with data
MIB_TCPROW row = new MIB_TCPROW();
row.dwState = 12;
byte[] bLocAddr = new byte[] { byte.Parse(locaddr[0]), byte.Parse(locaddr[1]), byte.Parse(locaddr[2]), byte.Parse(locaddr[3]) };
byte[] bRemAddr = new byte[] { byte.Parse(remaddr[0]), byte.Parse(remaddr[1]), byte.Parse(remaddr[2]), byte.Parse(remaddr[3]) };
row.dwLocalAddr = BitConverter.ToInt32(bLocAddr, 0);
row.dwRemoteAddr = BitConverter.ToInt32(bRemAddr, 0);
row.dwLocalPort = htons(int.Parse(loc[1]));
row.dwRemotePort = htons(int.Parse(rem[1]));
//Make copy of the structure into memory and use the pointer to call SetTcpEntry
IntPtr ptr = GetPtrToNewObject(row);
int ret = SetTcpEntry(ptr);
if (ret == -1) throw new Exception("Unsuccessful");
if (ret == 65) throw new Exception("User has no sufficient privilege to execute this API successfully");
if (ret == 87) throw new Exception("Specified port is not in state to be closed down");
if (ret != 0) throw new Exception("Unknown error (" + ret + ")");
}
catch (Exception ex)
{
throw new Exception("CloseConnection failed (" + connectionstring + ")! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
}
/// <summary>
/// Gets all connections
/// </summary>
/// <returns></returns>
public static string[] Connections()
{
return Connections(State.All);
}
/// <summary>
/// Gets a connection list of connections with a defined state
/// </summary>
/// <param name="state"></param>
/// <returns></returns>
public static string[] Connections(State state)
{
MIB_TCPROW[] rows = getTcpTable();
ArrayList arr = new ArrayList();
foreach (MIB_TCPROW row in rows)
{
if (state == State.All || state == (State)row.dwState)
{
string localaddress = IPIntToString(row.dwLocalAddr) + ":" + ntohs(row.dwLocalPort);
string remoteaddress = IPIntToString(row.dwRemoteAddr) + ":" + ntohs(row.dwRemotePort);
arr.Add(localaddress + "-" + remoteaddress + "-" + ((State)row.dwState).ToString() + "-" + row.dwState);
}
}
return (string[])arr.ToArray(typeof(System.String));
}
//The function that fills the MIB_TCPROW array with connectioninfos
private static MIB_TCPROW[] getTcpTable()
{
IntPtr buffer = IntPtr.Zero; bool allocated = false;
try
{
int iBytes = 0;
GetTcpTable(IntPtr.Zero, ref iBytes, false); //Getting size of return data
buffer = Marshal.AllocCoTaskMem(iBytes); //allocating the datasize
allocated = true;
GetTcpTable(buffer, ref iBytes, false); //Run it again to fill the memory with the data
int structCount = Marshal.ReadInt32(buffer); // Get the number of structures
IntPtr buffSubPointer = buffer; //Making a pointer that will point into the buffer
buffSubPointer = (IntPtr)((int)buffer + 4); //Move to the first data (ignoring dwNumEntries from the original MIB_TCPTABLE struct)
MIB_TCPROW[] tcpRows = new MIB_TCPROW[structCount]; //Declaring the array
//Get the struct size
MIB_TCPROW tmp = new MIB_TCPROW();
int sizeOfTCPROW = Marshal.SizeOf(tmp);
//Fill the array 1 by 1
for (int i = 0; i < structCount; i++)
{
tcpRows[i] = (MIB_TCPROW)Marshal.PtrToStructure(buffSubPointer, typeof(MIB_TCPROW)); //copy struct data
buffSubPointer = (IntPtr)((int)buffSubPointer + sizeOfTCPROW); //move to next structdata
}
return tcpRows;
}
catch (Exception ex)
{
throw new Exception("getTcpTable failed! [" + ex.GetType().ToString() + "," + ex.Message + "]");
}
finally
{
if (allocated) Marshal.FreeCoTaskMem(buffer); //Free the allocated memory
}
}
private static IntPtr GetPtrToNewObject(object obj)
{
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, false);
return ptr;
}
//Convert an IP string to the INT value
private static int IPStringToInt(string IP)
{
if (IP.IndexOf(".") < 0) throw new Exception("Invalid IP address");
string[] addr = IP.Split('.');
if (addr.Length != 4) throw new Exception("Invalid IP address");
byte[] bytes = new byte[] { byte.Parse(addr[0]), byte.Parse(addr[1]), byte.Parse(addr[2]), byte.Parse(addr[3]) };
return BitConverter.ToInt32(bytes, 0);
}
//Convert an IP integer to IP string
private static string IPIntToString(int IP)
{
byte[] addr = System.BitConverter.GetBytes(IP);
return addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3];
}
}
}
close(fd); /* comment to reach minimum size for an answer */