Get own socket port (NWConnection)

Hello,

it's possible to get the own socket port for NWConnection?
I open a network connection and will find out the used port on this created socket.

My example code:
Code Block
let queue = DispatchQueue(label: "UDP data thread")
let connection = NWConnection(host: "1.2.3.4", port: 40000, using: .udp)
connection.start(queue: queue)


IMHO it's totally simple code. Now I want to now the used socket port for my connection.

Where I can read this information? Many thanks.
Answered by Systems Engineer in 621168022
One thing I did want to follow up on is while there is no localEndpoint property on the NWConnection, there is one on the currentPath of the NWConnection. You can get the local port from here. Something like connection?.currentPath?.localEndpoint should work.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
If you are wanting the remote port for your NWConnection once it has gone into the ready state this will be available on via connection.endpoint. The local port is not that easy and there is no localEndpoint property available. You can see things like the interface your connection is bound to by using connection.currentPath. This should give you a result similar to interface: en0, ipv4, dns


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Accepted Answer
One thing I did want to follow up on is while there is no localEndpoint property on the NWConnection, there is one on the currentPath of the NWConnection. You can get the local port from here. Something like connection?.currentPath?.localEndpoint should work.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
Yeaaa great!

That here works really well:
Code Block
connection?.currentPath?.localEndpoint
Thanks!

It is also possible to determine myself which port is used?
For example: I want to receive data on local port 51234

I know that's possible with
Code Block
NWListener
but maybe it's also possible with NWConnection?

Glad that worked out for you. For assigning a local port on NWConnection, no, this is not available. Notice that connection?.currentPath?.localEndpoint only becomes populated with the local address and port once the connection goes into the .ready state. Even in the preparing state the port is still unknown.

NWListener is different because you want to tell the object to listen for incoming connections on a specific port. Very similar to binding (bind()) a listening socket for a port and accepting (accept()) client sockets connections that wish to connect. Except for NWListener takes care of all of this for you in user space.


Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
I wanted to update this thread because I just became aware of a new way to attempt to set the local port. (Thank you Quinn!) When setting up the NWConnection you can create a NWParameters object that creates a require requiredLocalEndpoint. For UDP, a brief example might look like:

Code Block swift
let params = NWParameters(dtls: nil, udp: .init())
params.requiredLocalEndpoint = NWEndpoint.hostPort(host: .ipv4(.any), port: 4000)
secureConnection = NWConnection(host: "x.x.x.x", port: 80, using: params)


A few caveats here:
1) You need to constrain the address family to either IPv4 or IPv6. (There is a bug created for this) (Thank you again Quinn!)

2) You will not see the local port go into usage until the connection enters the preparing state.

I tested this on a local and remote endpoint and was seeing the connection go into the ready state.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
OMG ... that sounds really great. You saved my day, many Thanks Matt and Quinn.
I don't know how many hours I've wasted to looking for this issue (without results).
No problem. Always glad to help.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com

How to print the connection port in the console when the app running without going in debugging?

connection?.currentPath?.localEndpoint this only work in debug when hit breakpont.

Thanks

I'm observing a strange behavior based on the nw_connection state. I'm running the client code that exercises the same query code listed below twice - once on nw_connection_state_preparing and the second on nw_connection_state_ready and getting a different source port.

nw_path_t path = nw_connection_copy_current_path(m_connection);
nw_endpoint_t endpoint = nw_path_copy_effective_local_endpoint(path);
uint16_t port = nw_endpoint_get_port(endpoint);

Can you please advise why and what is the correct state to get the source port on? The requirement on our side is to know the source port before the remote process accepts the connection.

Get own socket port (NWConnection)
 
 
Q