Enumerate all open connections - c#

Is it possible to enumerate all open connections of the current process using .NET? (similarly to the way the netstat tool does this)

You can do this with the IPGlobalProperties class in .NET. With an instance, you can get any of the three things that netstat generally shows:
Active TCP connections, via GetActiveTcpConnections()
Active TCP listeners, via GetActiveTcpListeners()
Active UDP listeners, via GetActiveUdpListeners()
Note that there's no such thing as a "UDP connection".
Here's a simple version of netstat, using this API:
using System;
using System.Net.NetworkInformation;
namespace NetStatNet
{
class Program
{
static void Main(string[] args)
{
var props = IPGlobalProperties.GetIPGlobalProperties();
Console.WriteLine(" Proto Local Address Foreign Address State");
foreach (var conn in props.GetActiveTcpConnections())
Console.WriteLine(" TCP {0,-23}{1,-23}{2}",
conn.LocalEndPoint, conn.RemoteEndPoint, conn.State);
foreach (var listener in props.GetActiveTcpListeners())
Console.WriteLine(" TCP {0,-23}{1,-23}{2}", listener, "", "Listening");
foreach (var listener in props.GetActiveUdpListeners())
Console.WriteLine(" UDP {0,-23}{1,-23}{2}", listener, "", "Listening");
Console.Read();
}
}
}

IPGlobalProperties properties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] connections = properties.GetActiveTcpConnections();
you have to convert this array to IEnum

Related

Send data to specific client from another client with a server in middle[C#]

I have searched everywhere but couldn't find as they are all answering to send message to all clients. What I want to achieve is multiple clients request to server to request data from another client and other client sends data to server telling it that data is for requesting client and so. I don't know how to achieve this. I'm new to this.
What I want to achieve:
I have tried with Data sending client to listen and requesting client to connect to it and transfer data. I have achieved this on local network but to make it work online it needs port forwarding and my user will be a lot of different people so port forwarding is not possible for every user. So I can rent a server which will act as a center of transfer. I programmed a test server in console which will listen to a server IP:port X and accept new clients and their data on port X and forward it to server IP:port Y but what this does is send data to all clients on port Y. I cannot send it to clients public ip address directly for obvious reasons. I understand that all the requesting clients are connected to port Y but I cannot create and assign new ports to all the clients interacting. So I want a way to determine how to request and receive the data without the need of assigning or creating new ports to different clients on same server.
What I have tried:
Server code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Test___server
{
class server
{
public static string serverIP = "192.168.0.102";
static void Main(string[] args)
{
Thread listenSendingThread = new Thread(listenSending);
listenSendingThread.IsBackground = true;
listenSendingThread.Start();
Thread listenReceivingThread = new Thread(listenReceiving);
listenReceivingThread.IsBackground = true;
listenReceivingThread.Start();
Console.ReadKey();
}
public static List<TcpClient> listSending = new List<TcpClient>();
public static List<TcpClient> listReceiving = new List<TcpClient>();
public static TcpClient clientSending = null;
private static void listenSending()
{
TcpListener listenerSending = new TcpListener(IPAddress.Parse(serverIP), 5319);
listenerSending.Start();
Console.WriteLine("Server listening to " + serverIP + ":5319");
while(true)
{
clientSending = listenerSending.AcceptTcpClient();
listSending.Add(clientSending);
Console.WriteLine("Sender connection received from " + clientSending.Client.RemoteEndPoint);
}
}
private static void send()
{
StreamWriter sw = new StreamWriter(clientSending.GetStream());
sw.WriteLine(message);
sw.Flush();
Console.WriteLine("Message sent!");
}
public static string message = string.Empty;
private static void listenReceiving()
{
TcpListener listener = new TcpListener(IPAddress.Parse(serverIP), 0045);
listener.Start();
Console.WriteLine("Server listening to " + serverIP + ":0045");
while (true)
{
TcpClient client = listener.AcceptTcpClient();
listReceiving.Add(client);
Console.WriteLine("Receiver connection received from " + client.Client.RemoteEndPoint);
StreamReader sr = new StreamReader(client.GetStream());
message = sr.ReadLine();
send();
}
}
}
}
Requesting client code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test____admin
{
class admin
{
static void Main(string[] args)
{
Console.WriteLine("Begin");
string serverIP = "192.168.0.102";
System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
clientSocket.Connect(serverIP, );
Console.WriteLine("Connected");
while (true)
{
Console.WriteLine("Reading");
StreamReader sr = new StreamReader(clientSocket.GetStream());
Console.WriteLine("Message: " + sr.ReadLine());
}
}
}
}
Request satisfying client code
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace Test___client
{
class client
{
public static string serverIP = "192.168.0.102";
static void Main(string[] args)
{
clientConnect();
}
private static void clientConnect()
{
try
{
TcpClient client = new TcpClient(serverIP, 0045);
StreamWriter sw = new StreamWriter(client.GetStream());
sw.WriteLine("Karan!");
sw.Flush();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}
You are using a very low-level API, and doing it the right way is challenging. Instead, try YARP as a reverse proxy. The requesting client should notify the reverse proxy about the desired destination client. One option is sending the destination client name in the request header. You will also need to split a single server request into multiple client requests, then merge their responses into a single one. You can achieve it by implementing Transphorms.
I'm not sure this approach applies to your situation because clients should implement server API using REST, Grpc or any other supported technology.

Sending udp packets between computers in C#

I am trying to send an udp packet from one computer to another in a local network. One computer is running Windows 10, other Ubuntu 18.04.
The code I have so far is this:
Server:
using System;
using System.Net.Sockets;
using System.Net;
namespace udpTest
{
class Program
{
static void Main(string[] args)
{
string hostName = Dns.GetHostName();
string ip = Dns.GetHostEntry(hostName).AddressList[0].ToString();
IPAddress ipadd = IPAddress.Parse(ip);
var serverEndPoint = new IPEndPoint(ipadd, 20020);
var udp = new UdpClient(ipadd.ToString(), 20020);
while (true) {
var recvData = udp.ReceiveAsync().Result;
System.Console.WriteLine($"received: {recvData.Buffer}");
}
}
}
}
Client:
using System;
using System.Net.Sockets;
using System.Net;
namespace C_
{
class Program
{
static void Main(string[] args)
{
var udp = new UdpClient();
var bytes = BitConverter.GetBytes(420);
var i = udp.SendAsync(bytes, bytes.Length, "fe80::7077:8d67:4984:c9bc%43", 20020 ).Result;
System.Console.WriteLine($"sent: {i}");
}
}
}
(I changed the ipv6 address a bit but format is exactly the same).
I get no errors when sending or anything, it just goes through but the server does not catch it. I have no idea what I am doing wrong. So any pointers would be most appreciated.
Edit: updated code works within lan, but not outside LAN.
Client:
static void Main(string[] args)
{
var udp = new UdpClient("192.168.1.117", 20020);
var bytes = BitConverter.GetBytes(420);
var i = udp.SendAsync(bytes, bytes.Length).Result;
System.Console.WriteLine($"sent: {i}");
}
Server:
static void Main(string[] args)
{
var serverEndPoint = new IPEndPoint(IPAddress.Any, 20020);
var udp = new UdpClient(serverEndPoint);
while (true) {
var recvData = udp.ReceiveAsync().Result;
System.Console.WriteLine($"received: {recvData.Buffer}");
}
}
first try IPAddress.Any since using the first IP address from Dns.GetHostEntry(hostName).AddressList[0].ToString(); is not guaranteed to be the IPv6 address you are using, specially if the computer has more than one network adapter.
Second is using the serverEndPoint you created for the UdpClient constructor
// Use IPAddress.Any
IPAddress ipadd = IPAddress.Any;
var serverEndPoint = new IPEndPoint(ipadd, 20020);
// Use the serverEndPoint for the UP
var udp = new UdpClient(serverEndPoint);
Third, check the server's firewall settings and make sure you allow incoming UDP messages on port 20020 (by default on both Windows and Ubuntu it is not allowed). And check the client firewall settings and make sure outgoing UDP messages on port 20020 are allowed (by default on both Windows and Ubuntu it is allowed).

Get name of bluetooth device on the Devices and Printers window

I know there are questions out there referring to gathering the friendly name of a device on the Device Manager but I cannot do this as the device is simply referred to as "Stardard Serial over Bluetooth link (COM)" and I have many virtual ports with the same reference. I want the name of the device as shown on the Devices and Printers window on:
I'm doing this in C# and currently just getting a list of available COM ports on the system and selecting the one I know from memory.
I managed to get it to work using 32Feet.Net.
You can search for a device by doing
BluetoothClient client = new BluetoothClient();
devices = client.DiscoverDevicesInRange();
foreach (BluetoothDeviceInfo d in devices)
{
items.Add(d.DeviceName);
}
This will give a list of the friendly names you see on the Devices and Printers window rather than "Standard serial over Bluetooth Link".
If you want the COM port like me or any other piece of information then you can simply do a WMI query such as
System.Management.ManagementObjectSearcher Searcher = new System.Management.ManagementObjectSearcher("Select * from WIN32_SerialPort");
foreach (System.Management.ManagementObject Port in Searcher.Get())
{
//your comparison or code here
}
I managed to get the bluetooth name, address and the COM port number without using the 32feet.net library by fiddling with the registry key.
Then, you could connect the bluetooth device by using the SerialPort class by passing the COM port number.
The pseudo code to obtain the bluetooth information is below:
enumerate all the COM port available in the PNP
obtain the device classGuid
search the bluetooth address from the classGuid
when the bluetooth address is known, the bluetooth name can be obtained from - this registry SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices
I have posted my code in the link below:
https://stackoverflow.com/a/36298213/2297825
I'm using my custom code using 32feet.Net Library which helps me to get the Device Friendly Name also COM port information attached with that device in C# Console Application.
I'm using below code to detect Topaz-Signature Device, and its friendly Name is "T-S460-BT2". You can replace this
string FriendlyDeviceName = "T-S460-BT2";
in the code with your device name you want to search.
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Bluetooth.Widcomm;
using InTheHand.Net.Sockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using System.Text.RegularExpressions;
namespace SearchDevice
{
class Program
{
static void Main(string[] args)
{
string FriendlyDeviceName = "T-S460-BT2";
if (BluetoothRadio.IsSupported)
{
BluetoothClient client = new BluetoothClient();
BluetoothDeviceInfo[] devices;
devices = client.DiscoverDevicesInRange();
foreach (BluetoothDeviceInfo d in devices)
{
if (Regex.IsMatch(d.DeviceName, FriendlyDeviceName, RegexOptions.IgnoreCase))
{
try
{
string query = string.Format("SELECT Name, DeviceID, PNPDeviceID from WIN32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
ManagementObjectCollection osDetailsCollection = searcher.Get();
foreach (ManagementObject mo in osDetailsCollection)
{
string PNPDeviceID = (string)mo.GetPropertyValue("PNPDeviceID");
if (PNPDeviceID != null && Regex.IsMatch(PNPDeviceID, d.DeviceAddress + "", RegexOptions.IgnoreCase))
{
Console.WriteLine("{0}", ((string)mo.GetPropertyValue("DeviceId")).Replace("COM", ""));
}
}
}
catch (Exception exx)
{
}
}
}
}
else
{
Console.WriteLine("Not Supported");
}
Console.ReadLine();
}
}
}

SharpSVN connection rate limit to localhost?

We use SharpSVN to programmatically access SVN repositories. Now we have the problem that the access to local repositories via svn:// or http:// urls is very slow - every access needs at least one second, and our app needs to fetch a bunch of properties and directory listings.
We could reproduce the problem on two different machines, both are Windows 7 32 bit and are in the same domain. The SVN servers are VisualSVN 2.1.9 for http:// urls and the CollabNet 1.6.17 for svn:// urls. It appears for connections via "localhost" and via the host name. It appears in our C# application, as well as a small testbed app using IronPython and when calling the SharpSvn svn.exe command.
This problem does not happen when accessing when accessing remote repositories (Both a linux and a windows XP server) - here, each access is between 0.01 and 0.08 secs, which is expected due to network latency. The Problem also does not happen when acessing the local repositories via file:// urls or when accessing the repositories via "native" svn command line tools from CollabNet.
Now my question is: Has Windows 7 or .NET or SharpSVN some built-in limit which only applies to localhost connections?
(Addition: I now found out that this limit also applies when connecting via a small C# test program using System.Net.Sockets.TcpClient:
Server:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace TcpSpeedServer
{
class Program
{
public static void Main()
{
Int32 port = 47011;
IPAddress localAddr = IPAddress.Parse("127.0.0.1");
var server = new TcpListener(localAddr, port);
server.Start();
Console.WriteLine("Listening on {0} : {1}", localAddr, port);
ulong count = 0;
// Enter the listening loop.
while(true)
{
using (var client = server.AcceptTcpClient()) {
Console.WriteLine("Connected: {0} {1}!", count, client.Client.RemoteEndPoint);
count += 1;
using (var stream = client.GetStream()) {
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
{
string query = reader.ReadLine();
writer.WriteLine("GET / HTTP/1.0");
writer.WriteLine();
writer.Flush();
}
}
}
}
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Threading;
namespace TcpSpeedTest
{
class Program
{
const bool ASYNC = false;
static DateTime s_now;
public static void Main(string[] args)
{
var liste = new List<object>();
s_now = DateTime.Now;
for (int i=0; i < 100; i += 1) {
if (ASYNC)
ThreadPool.QueueUserWorkItem(connect, i);
else
connect(i);
}
Console.WriteLine("outer: " + (DateTime.Now - s_now));
Console.ReadLine();
}
private static void connect(object i)
{
DateTime now = DateTime.Now;
using (TcpClient client = new TcpClient("localhost", 47011))
{
var stream = client.GetStream();
using (StreamWriter writer = new StreamWriter(stream))
using (StreamReader reader = new StreamReader(stream))
{
writer.WriteLine("GET / HTTP/1.0");
writer.WriteLine();
writer.Flush();
string result = reader.ReadLine();
}
}
Console.WriteLine(string.Format("inner: {0} - {1} - {2}", i, DateTime.Now - now, DateTime.Now - s_now));
}
}
}
So this problem seems not to be subversion specific.)
Addition2: When running the client under Mono 2.10 for windows, the problem does not appear. So it seems to be specific to .NET framework.
Addition3: It seems to be an IPv6 related problem. The server only listens on IPv4, but the hostname also resolves to IPv6. Now it seems that the OS code internally tries the IPv6 connection, and after getting the connection reset, waits 1 sec before falling back to IPv4. And this game is repeated for every single connection attempt. http://msdn.microsoft.com/en-us/library/115ytk56.aspx documents that for TcpClient (thanks to Andreas Johansson from the MSDN forums for the hint!), and it seems that the APR used by Apache internally uses a similar mechanism.
Addition 3 is also the solution to your problem. To fix this, either make DNS/hosts file only resolve to an IPv4 address, or make the IPv6 server(s) work.
You can enter in C:\Windows\System32\drivers\etc\hosts something like:
127.0.0.1 localhost-ipv4
And then use that name to connect.
You can also make svnserve listen to IPv6 addresses. A quick search for svnserve options [revealed][1] that it defaults to IPv6, so in its startup parameters is probably a --listen-host. Try removing that, or when it's not present forcing it to run at IPv6.
The same can be done for the Apache webserver:
Listen 0.0.0.0:80
Listen [::]:80

List used TCP port using C#

This is the answer to my questions.
How to list binded/used TCP port in C#. Used modified code from jro
static void ListUsedTCPPort(ref ArrayList usedPort)
{
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpListeners();
IEnumerator myEnum = tcpConnInfoArray.GetEnumerator();
while (myEnum.MoveNext())
{
IPEndPoint TCPInfo = (IPEndPoint)myEnum.Current;
usedPort.Add(TCPInfo.Port);
}
}
Original questions.
This is how i list TCP port using C#. It is modified code i found in this forum(forgot exactly where i got it. If you are the original developer, notify me and ill put credits where due.)
//List used tcp port
static void ListUsedTCPPort(ref ArrayList usedPort)
{
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
IEnumerator myEnum = tcpConnInfoArray.GetEnumerator();
while (myEnum.MoveNext())
{
TcpConnectionInformation TCPInfo = (TcpConnectionInformation)myEnum.Current;
usedPort.Add(TCPInfo.LocalEndPoint.Port);
}
}
Problem is, the results is different from used tcp port listed in TCPview(Protocol-TCP, Local port).
By the way, i do know that this list used TCP port at the EXACT time its called.
What did i did wrong?
I get the same result:
But it does also show listeners (ipGlobalProperties.GetActiveTcpListeners()) which may or may not be closed down.
using your example (with an extra Console.WriteLine in there
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Collections;
namespace ConsoleApplication1 {
static class Program {
//List used tcp port
static void ListAvailableTCPPort(ref ArrayList usedPort) {
IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
IEnumerator myEnum = tcpConnInfoArray.GetEnumerator();
while (myEnum.MoveNext()) {
TcpConnectionInformation TCPInfo = (TcpConnectionInformation)myEnum.Current;
Console.WriteLine("Port {0} {1} {2} ", TCPInfo.LocalEndPoint, TCPInfo.RemoteEndPoint, TCPInfo.State);
usedPort.Add(TCPInfo.LocalEndPoint.Port);
}
}
public static void Main(){
ArrayList usedPorts = new ArrayList();
ListAvailableTCPPort(ref usedPorts);
Console.ReadKey();
}
}
}
It's a bit of a guess but TCPView probably also shows listener tcp ports (ipGlobalProperties.GetActiveTcpListeners())

Categories

Resources