C# UDPClient pass variable as port value - c#

This is my code:
UdpClient server = new UdpClient(5001);
My question is: i want to pass the port value (5001), from an int variable. Is this possible?
Example:
UDPClient server = new UDPClient(intvariable);
Thank you!

The constructor of the UpdClient is Int32 so you can do so.
int variable = value;
UDPClient server = new UDPClient(variable);
Here's the definition of the UpdClient class

You can set up the address and port in the constructor, just take a look at the documentation http://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient%28v=vs.110%29.aspx
So you could have
int portNumber = 12345;
string ipAddress = 127.0.0.1 //You can also use a web address instead.
UDPClient newClient - new UDPClient(ipAddress, portNumber);
Alternatively you can put nothing in the constructor and do the specify a destination when you connect. This allows you to get user input first rather than hard coding the address and port.
int portNumber = 12345;
string ipAddress = 127.0.0.1 //You can also use a web address instead.
UDPClient newClient - new UDPClient();
newClient.Connect(IpTextBox.text(), Convert.ToInt32(portNumberTB.Text() );
Remember if you are reading user input for your address and port then you will need error handling.

The constructor of UdpClient cannot tell the difference between new UdpClient(1234) and
int port = 1234; new UdpClient(port);
For that reason there cannot possibly be a difference. 1234 and port are expressions of the same value. That's the only thing that counts.

Thank you for the answers.
The code you people gave me was correct. My code aswell.
My problem occurs in the declaration of the UDPClient objects. The declaration happens
during the initialization of a windows form application.

Related

How to get the assigned port of a GrpcServer

I want to create a gRPC server and bind it to a random port.
The documentation states that port 0 (ServerPort.PickUnused = 0) can be passed to achieve this:
var server = new Server
{
Ports = { new ServerPort("0.0.0.0", ServerPort.PickUnused, ServerCredentials.Insecure) }
};
// ... adding some services
server.Start();
How can I determine which port has been assigned to the server?
The passed ServerPort still mentions 0:
var enumerator = server.Ports.GetEnumerator();
enumerator.MoveNext();
var serverPort = enumerator.Current as ServerPort;
Debug.Log($"RPC Server started on port {serverPort.Port}");
// Out: RPC Server started on port 0
Sometimes reading the WHOLE documentation page BEFORE googling around would save so much time.
ServerPort has a property named BoundPort (quote: "The port actually bound by the server.
This is useful if you let server pick port automatically.")
This returns the actual port:
Debug.Log($"RPC Server started on port {serverPort.BoundPort}");

How to use tcplistener and tcpclient on device and computer with different ip in same Network?

I'm trying to communicate with a modbus device in my network at ip 192.168.1.76. My host computer address is 192.168.1.132. I'm not able to connect to or listen to device ip.
basically i'm using NModbus4 library. I've created a ModbusTCPSlave and attached the tcp listener to it. then i assigned ModbusSlaveRequestReceived event to that slave. but it gives nothing in return when i try to change register values directly from Modscan software.
Main()
{
var masterEndpoint = new IPEndPoint(IPAddress.Parse("192.168.1.132"), 502);
var listener = new TcpListener(IPAddress.Any, 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, new TcpListener(masterEndpoint), 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();
}
private static void Modbus_Request_Event(object sender, Modbus.Device.ModbusSlaveRequestEventArgs e)
{
//disassemble packet from master
byte fc = e.Message.FunctionCode;
byte[] data = e.Message.MessageFrame;
byte[] byteStartAddress = new byte[] { data[3], data[2] };
byte[] byteNum = new byte[] { data[5], data[4] };
Int16 StartAddress = BitConverter.ToInt16(byteStartAddress, 0);
Int16 NumOfPoint = BitConverter.ToInt16(byteNum, 0);
Console.WriteLine(fc.ToString() + "," + StartAddress.ToString() + "," + NumOfPoint.ToString());
}
I expect to get function code, start address and number of points in console application when any register value is changed
I copied your code. Changed the IP address to my "server" and it worked.
So, the issue you are having is either in the setup of your "server" or in the PLC program.
I thought that I had to do some port forwarding on my router. I did not. It did not make a difference.
Server setup:
Your "server"'s IP address needs to be static. Whether your 'server' is your development system or not. And don't forget when you deploy... Server's IP address has to be static as well (not that it wouldn't be...just saying)
Add an inbound Firewall rule to allow connections to the port, in this case 502, otherwise you'll have to allow access every time you launch/start a test.
PLC program
I am using Click PLC's by Koyo. Not sure if this is the rule for all PLC's or not; but, we had to add a line of code to "write" the values we wanted to pick up off the TCP stream. Without the write, the PLC was not sending out a request to join the TcpListener.
Last:
The code to start your listener only needs to be this:
var listener = new TcpListener(IPAddress.Parse("192.168.1.244"), 502);
listener.Start();
var slave = ModbusTcpSlave.CreateTcp(255, listener, 10);
slave.ModbusSlaveRequestReceived += Modbus_Request_Event;
slave.Listen();

c# TCPclient set IP

I'm trying to send a packet using httpclient
TcpClient tc = new TcpClient(ip, 4500);
string s = "A7007000601D3B00";
byte[] arr = new byte[s.Length/2];
for ( var i = 0 ; i<arr.Length ; i++ ){
arr[i] = (byte)Convert.ToInt32(s.Substring(i*2,2), 16);
}
NetworkStream stream = tc.GetStream();
stream.Write(arr, 0, arr.Length);
tc.Close();
The problem is that it sends from port 47109, however i need to send the packet using port 46324. How do i set this?
There is an overload of the TcpClient constructor that allows you to bind it to a specific local IP address and port. See the documentation on MSDN.
The reason the example at Is there a way to specify the local port to used in tcpClient? is not working is probably because the first address on the list is not actually the local machine ip address. Something like this might fix the issue and pull the proper local IP address:
string remoteIP = "x.x.x.x";
IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(x => x.AddressFamily == AddressFamily.InterNetwork).First();
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, 47109);
TcpClient clientSocket = new TcpClient(ipLocalEndPoint);
clientSocket.Connect(remoteIP, 4500);

Get the IpAddress on which we received an UDP Multicast request

I'm using an UdpClient to read data from a multicast group.
It's configured like this:
m_udpClientReceiver = new UdpClient();
m_receivingEndPoint = new IPEndPoint(IPAddress.Any, m_port);
m_udpClientReceiver.ExclusiveAddressUse = false;
m_udpClientReceiver.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
m_udpClientReceiver.ExclusiveAddressUse = false;
m_udpClientReceiver.Client.Bind(m_receivingEndPoint);
m_udpClientReceiver.JoinMulticastGroup(m_multicastAddress, 255);
and I read it with:
Byte[] data = m_udpClientReceiver.Receive(ref m_receivingEndPoint);
I've several network cards(two LAN, one wifi), that are bound on differents subnets. I need to know on which network card(which ip in fact) the request has been received.
How can I achieve this?
Thank you!
As an alternative have you considered not joining a multicast group? You can send and receive multicast packets just as easily using the standard UDPClient class. i.e.
UdpClient.Send(byte[] dgram, int bytes, IPEndPoint endPoint)
where endPoint = new IPEndPoint(IPAddress.Broadcast, <port number>). And on the receive still using:
Byte[] data = m_udpClientReceiver.Receive(ref m_receivingEndPoint);
where m_receivingEndPoint is now correctly set? I've just tested this and it works fine.
I'm finally using the BeginReceive method(async), and I'm giving as context the ip on which it's bound

Specifying what network interface an UDP multicast should go to in .NET

On a computer with both an active Wireless Card and a LAN-Port with a crossover cable hooked up to another machine running the same application, we need to send a UDP multicast over the LAN wire to the other computer. Using C# Sockets, Windows seems to try to route the message over the WLAN adapter every time.
Is there a way to specify what network interface to send a UDP multicast on?
Just as addendum to Nikolai answer: the problem with KB318911 is a dirty trick that user must provide necessary adapter index. While looking how to retrieve this adapter index I figured out such recipe:
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties ip_properties = adapter.GetIPProperties();
if (!adapter.GetIPProperties().MulticastAddresses.Any())
continue; // most of VPN adapters will be skipped
if (!adapter.SupportsMulticast)
continue; // multicast is meaningless for this type of connection
if (OperationalStatus.Up != adapter.OperationalStatus)
continue; // this adapter is off or not connected
IPv4InterfaceProperties p = adapter.GetIPProperties().GetIPv4Properties();
if (null == p)
continue; // IPv4 is not configured on this adapter
// now we have adapter index as p.Index, let put it to socket option
my_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(p.Index));
}
Full note at http://windowsasusual.blogspot.ru/2013/01/socket-option-multicast-interface.html
You are probably looking for SocketOptionName.MulticastInterface. Here's an article on MSDN that might help you.
Other then that if you update your local routing table to have an exact entry matching the multicast address and pointing to the right interface it should just work.
Depending on what you're doing, there's a Win32 method that might help. It'll return the best interface for a given IP address. To get the default one (the 0.0.0.0), which is usually what you want for multicast, it's pretty easy:
P/Invoke signature:
[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
private static extern int GetBestInterface(UInt32 DestAddr, out UInt32 BestIfIndex);
Then somewhere else:
// There could be multiple adapters, get the default one
uint index = 0;
GetBestInterface(0, out index);
var ifaceIndex = (int)index;
var client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(ifaceIndex));
var localEndpoint = new IPEndPoint(IPAddress.Any, <port>);
client.Client.Bind(localEndpoint);
var multicastAddress = IPAddress.Parse("<group IP>");
var multOpt = new MulticastOption(multicastAddress, ifaceIndex);
client.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, multOpt);
var broadcastEndpoint = new IPEndPoint(IPAddress.Parse("<group IP>"), <port>);
byte[] buffer = ...
await client.SendAsync(buffer, buffer.Length, broadcastEp).ConfigureAwait(false);
If you are using UDPClient class, then this method forces the IGMP message out of the interface you desire (second parameter), even when binding doesn't work.
receiveUDPClient.JoinMulticastGroup(IPAddress.Parse("239.254.2.1"), IPAddress.Parse("192.168.6.1"));
Otherwise, MulticastOption(IPAddress, IPAddress) will work. The first parameter is the multicast address, the second address forces a localendpoint you specify to be used.

Categories

Resources