-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Add Source-Process Property to TcpConnectionInformation #63099
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/ncl Issue DetailsBackground and motivationLibraries such as the ones made by dotpcap would benefit greatly to provide the source of internet traffic. And I know it's possible under Windows and should be under Linux. That's what I've gathered from my research and prototyping. I am very open to anyone with great experience to hook in and suggest and discuss the possibilities for this to work. I know that, under Linux, API Proposalnamespace System.Net.NetworkInformation
{
/// <summary>
/// Provides information about the Transmission Control Protocol (TCP) connections on the local computer.
/// </summary>
public abstract class TcpConnectionInformation
{
/// <summary>
/// Gets the source-Process of the Transmission Control Protocol (TCP) connection.
/// </summary>
public abstract Process Process { get; }
/// <summary>
/// Gets the local endpoint of a Transmission Control Protocol (TCP) connection.
/// </summary>
public abstract IPEndPoint LocalEndPoint { get; }
/// <summary>
/// Gets the remote endpoint of a Transmission Control Protocol (TCP) connection.
/// </summary>
public abstract IPEndPoint RemoteEndPoint { get; }
/// <summary>
/// Gets the state of this Transmission Control Protocol (TCP) connection.
/// </summary>
public abstract TcpState State { get; }
}
} API Usageusing System.Net.NetworkInformation;
var properties = IPGlobalProperties.GetIPGlobalProperties();
foreach (var connection in properties.GetActiveTcpConnections())
{
Console.WriteLine(
"{0}: [{1}] {2} <=> {3}",
connection.Process.ProcessName,
connection.State,
connection.LocalEndPoint,
connection.RemoteEndPoint
);
}
/*
Example Output:
Foo: [Established] 192.168.1.1:8000 <=> 123.123.123.123:443
System: [TimeWait] 192.168.1.1:2225 <=> 100.100.100.100:6000
Discord: [TimeWait] 192.168.1.1:5050 <=> 80.81.8.10:5050
...
*/ Alternative DesignsNo response RisksI would know how to hack something together for both, Windows & Linux. My prototype seems performance taxing for Windows
Mind, my prototype consists of using Lists, tuples and probably lots of other taxing data structures and ways. public List<(Process, MIB_TCPROW_OWNER_PID)> GetTcpInformationNew()
{
var result = new List<(Process, MIB_TCPROW_OWNER_PID)>();
var connections = IPStuff.GetAllTCPConnections(); // P/Invoke
var processes = Process.GetProcesses();
for (int i = 0; i < connections.Count; i++)
{
var connection = connections[i];
Process process = null;
for (int j = 0; j < processes.Length; j++)
{
var localProcess = processes[j];
if (connection.ProcessId == localProcess.Id)
process = localProcess;
}
result.Add((process, connection));
}
return result;
} I am not sure yet how taxing it would be to iterate through all Seemingly chaotic, but it makes sense. 😄
An example program which continuously sends data through a tcp connection, taking up port 8000 (An example target what I am looking for)
Getting my example program's process id (3793) to simulate and skip the process of scanning through all
So see this as a bump of an idea, as I know it's possible and great software such as Fiddler and alike do this since forever, for windows at least.
|
Why not just return the source process' PID? Currently the And why are you using |
Well, how user-friendly would it be to return / provide numeral id's over a process object
It can happen, that sockets are being shut down and no longer associated with a process. Process running with an associated open socket: (https://www.howtouselinux.com/post/tcp_time_wait_linux) From some benchmarking, I came to the conclusion, that a consistent ~2ms time would be better than ~0.003ms and occasional ~6ms cases. HoweverI just did some confirmation benchmarks, and now I am seeing different results. Seeing this confirmation I think you're right, there is practically no significant difference. So I'd say the GetProcessById_CatchFail() would be the go-to solution
public class TcpConnectionInfoPrep
{
private int ProgramProcessId;
[GlobalSetup]
public void Setup()
{
ProgramProcessId = Process.GetCurrentProcess().Id;
}
[Benchmark]
public Process[] GetProcesses()
=> Process.GetProcesses();
[Benchmark]
public Process GetProcessById()
=> Process.GetProcessById(ProgramProcessId);
[Benchmark]
[Arguments(-1)]
public Process GetProcessById_SafeFailLinq(int id)
=> Process.GetProcesses().FirstOrDefault(_ => _.Id == id);
[Benchmark]
[Arguments(-1)]
public Process GetProcessById_SafeFail(int id)
{
var processes = Process.GetProcesses();
for(int i = 0; i < processes.Length; i++)
{
var curProc = processes[i];
if (curProc.Id == id)
return curProc;
}
return null;
}
[Benchmark]
[Arguments(-1)]
public Process GetProcessById_CatchFail(int id)
{
try
{
return Process.GetProcessById(id);
}
catch
{
return null;
}
}
} |
A PID is a well-known concept. If we name it |
Oh, does Process.GetProcess*() spawn new Process objects, or are they managed and chached within? |
No, they are not cached. |
I agree a While I have no objection to the property itself, I have a hard time swallowing that change in performance which I suspect would become prohibitive in a server environment with thousands of open sockets. Can we find a better way to implement this, to make it optional, or to refactor the API in a way that doesn't affect the performance for current users? |
I have been thinking about this. Option 1: Option 2: It can't be that for Windows it's a singluar win api function call to get all information at once; I've made some prototyping to get the mentioned approach for linux to work and turns out, if I was to add the process id gathering to Which is horrible, but makes sense. As a side note, that is how on linux both I'd love to see a linux equivalent to |
Found a discussion on this topic in a WireShark issue: More specifically I'd like to point out the following: |
Triage:
|
@karelz as a side note: GetActiveTcpConnections() already isn't supported for android, see: |
Triage: We will close the API proposal in current form. Even the "new" potential API form seems to be fairly corner-case scenario. We would probably want to see more usage cases before adding such API. @tmds perhaps it might be exposed in your extension library? Let us know if you disagree, or if we missed some points. Thanks! |
Background and motivation
Libraries such as the ones made by dotpcap would benefit greatly to provide the source of internet traffic. And I know it's possible under Windows and should be under Linux. That's what I've gathered from my research and prototyping.
I am very open to anyone with great experience to hook in and suggest and discuss the possibilities for this to work.
I've looked into finding an API from glibc and alike for Linux, which I could P/Invoke, as I do with Windows, but no luck with that.
I'd be happy - grateful even - if someone knows a better way to fetch the information, as this is rather unordinary territory for me.
I know that, under Linux,
netstat -ano -p tcp
andss -p
provide both information, port & processid.So a quick
strace
on both showed me, that they're both doing what I am about to propose as approach for Linux - Fetching lots of directory info.API Proposal
API Usage
Alternative Designs
No response
Risks
I would know how to hack something together for both, Windows & Linux.
However, for Windows it involves, besides a P/Invoke, to iterate through all connections and potentially all processes to match the id with a Process object.
For Linux, it involves, besides reading from
/proc/net/tcp
, to also iterate through all directories in/proc/
to match the/proc/net/tcp
's gathered socket INode id with the one read from/proc/{processid}/fd
's socket file.(I would like to point out the last paragraph of Background and motivation for this)
My prototype seems performance taxing for Windows
GetTcpInformation
being the original vanillaIPGlobalProperties.GetActiveTcpConnections()
And
GetTcpInformationNew
my prototype with a P/Invoke, and two iterations through all open connections and potentially all running processesMind, my prototype consists of using Lists, tuples and probably lots of other taxing data structures and ways.
I am not sure yet how taxing it would be to iterate through all
/proc/*
directories and list each individual sub-directories of/proc/{processId}/fd
to parse and filter.Here an example:
Seemingly chaotic, but it makes sense. 😄
An example program which continuously sends data through a tcp connection, taking up port 8000 (An example target what I am looking for)
Getting my example program's process id (3793) to simulate and skip the process of scanning through all
/proc/
directories and directly navigate to the right folder to see resultcat /proc/net/tcp
to view all open tcp connections including the socket's inode from our target portls /proc/3793/fd -l
containing the process id (which we know) from a "simulated" iteration through all folders, now at the point of finding the folder of which contains the socket with the target inode (socket[52096]
)So see this as a bump of an idea, as I know it's possible and great software such as Fiddler and alike do this since forever, for windows at least.
The text was updated successfully, but these errors were encountered: