we're trying to set up a test bench in Vector's CANoe for a ECU that uses BroadR-Reach. Therefore, we want to send and receive UDP messages. We tried with the UdpClient class and the BeginSend/BeginReceive methods. Sending messages works, but for some reasons the execution of the test node stops when we try to receive a message.
Here is the code:
using System;
using System.Net;
using Vector.Tools;
using Vector.CANoe.Runtime;
using Vector.CANoe.Threading;
using Vector.CANoe.TFS;
using Vector.CANoe.Sockets;
using System.Threading;
using NetworkDB;
public class TestPingBroadRReach1 : TestModule
{
private byte channel = 6;
private ushort pingCount = 0;
public static bool messageReceived = false;
public struct UdpState
{
public UdpClient u;
public IPEndPoint e;
}
public override void Main()
{
// Test sequence definition
PingTest();
}
[TestCase("SYS4_TC4321", "BroadR-Reach 1: Ping test", "Checks if a ping is answered on BroadR-Reach 1")]
public void PingTest()
{
// setup UDP client
Report.TestStep("Setup UDP client.");
IPEndPoint e = new IPEndPoint(IPAddress.Any, 0xC09F);
UdpClient udpClient = new UdpClient(e);
UdpState s = new UdpState();
s.e = e;
s.u = udpClient;
IAsyncResult receiveResult = udpClient.BeginReceive(new AsyncCallback(UdpReceiveFinished), s);
//UdpClient u = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.1.1"), 0xC09F));
UdpClient u = new UdpClient();
byte[] pingRequest = this.CreatePingRequest();
// send the message
// the destination is defined by the server name and port
u.Connect(new IPEndPoint(IPAddress.Parse("192.168.1.80"), 0xBB9));
u.BeginSend(pingRequest, pingRequest.Length, new AsyncCallback(UdpSendFinished), u);
int i = 0;
while (!messageReceived && i < 50)
{
Thread.Sleep(100);
++i;
}
private void UdpSendFinished(IAsyncResult result)
{
UdpClient u = (UdpClient)result.AsyncState;
Output.WriteLine("UdpSendFinished");
u.EndSend(result);
}
private void UdpReceiveFinished(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).u;
IPEndPoint e = ((UdpState)(ar.AsyncState)).e;
byte[] receiveBytes = u.EndReceive(ar, ref e);
Output.WriteLine("UdpReceiveFinished");
messageReceived = true;
}
}
Does anybody has an example for receiving UDP messages with CANoe and C#? That would be great, thank's!
Related
I'm trying to figure out how I can send & receive data via the UDP protocol using C# as a client, and having a JS server running that will transmit a "response" packet for testing purposes.
Below is the UDP class that I made for testing, it's simply just 2 threads:
One that read the received data from UDP and another thread for sending data.
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace UDPTesting {
class UDPHandler {
private int receivePort, sendPort;
private string serverIP;
private IPEndPoint sendEndPoint, receiveEndPoint;
public UDPHandler(string serverIP, int receivePort, int sendPort) {
this.serverIP = serverIP;
this.receivePort = receivePort;
this.sendPort = sendPort;
this.sendEndPoint = new IPEndPoint(IPAddress.Parse(this.serverIP), this.sendPort);
this.receiveEndPoint = new IPEndPoint(IPAddress.Parse(this.serverIP), this.receivePort);
this.readerUdpClient();
this.senderUdpClient();
}
void readerUdpClient() {
UdpClient readerClient = new UdpClient();
IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 3000);
readerClient.Client.Bind(localEndpoint); //Tried both Connect and Bind
//readerClient.Connect(this.receiveEndPoint);
Thread t = new Thread(() => {
Console.WriteLine("Awaiting data from server...");
var remoteEP = new IPEndPoint(IPAddress.Any, 3000);
byte[] bytesReceived = readerClient.Receive(ref remoteEP);
//The above throws: System.InvalidOperationException: 'You must call the Bind method before performing this operation'
Console.WriteLine("Received data from " + remoteEP.ToString());
});
t.Start();
}
void senderUdpClient() {
UdpClient senderClient = new UdpClient();
senderClient.Connect(this.sendEndPoint);
string sendString = "1;2;3";
byte[] bytes = toBytes(sendString);
Thread t = new Thread(() => {
while (true) {
senderClient.Send(bytes, bytes.Length);
Thread.Sleep(1000);
}
});
t.Start();
}
public byte[] toBytes(string text) {
return Encoding.UTF8.GetBytes(text);
}
public string fromBytes(byte[] bytes) {
return Encoding.UTF8.GetString(bytes);
}
}
}
Additionally my "main" for my program is this:
using System;
using System.Threading;
namespace UDPTesting {
class Program {
static void Main(string[] args) {
string serverIP = "46.101.102.243";
int sendPort = 41234;
int receivePort = 3000;
UDPHandler handler = new UDPHandler(serverIP, receivePort, sendPort);
}
}
}
How can I read the response that the server sends in the client, at the same time as I send data from the client to the server?
We tested it individually:
1) Sending a UDP packet from client -> server works, as I can see that the server receives the packet.
2) Sending a UDP packet from server -> client works, as I can see the client receives the packet.
3) When the client tries to send and read simultaneously, it will send data to the server, but will not read the response.
Any help would be greatly appreciated!
Your receiving function should work like this
void readerUdpClient()
{
new Thread(() => {
UdpClient readerClient = new UdpClient(receivePort);
Console.WriteLine("Awaiting data from server...");
var remoteEP = new IPEndPoint(IPAddress.Any, 0);
byte[] bytesReceived = readerClient.Receive(ref remoteEP);
Console.WriteLine($"Received {bytesReceived.Length} bytes from {remoteEP}");
}).Start();
}
The UdpClient constructor that takes a port automatically binds the local end point for you.
First of all, i'm new to all this Stack Overflow thingy.
I'm mostly a Unity programmer, but i need to run some code on my Pi and Unity can't build for it. Therefore, i'm using C# so i can later build with Mono.
I have a basic socket server code that runs off of unity, and it works fine.
I tried porting it over to VS but i always get a Null Ref Exception when calling Socket.Accept.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class RasPi
{
IPAddress ipAddress;
IPEndPoint localEndPoint;
Socket listener;
Socket handler;
int i = 0;
string data = string.Empty;
public string IP = "192.168.10.5";
public int Port = 5001;
static void Main(string[] args)
{
new RasPi().Initialize();
new RasPi().StartListening();
}
void Initialize()
{
i = 0;
ipAddress = IPAddress.Parse(IP);
localEndPoint = new IPEndPoint(ipAddress, Port);
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(10);
}
public void StartListening()
{
try
{
while (true)
{
if (i == 0)
{
Console.WriteLine(listener.Accept());
handler = listener.Accept();
}
data = string.Empty;
while (true)
{
byte[] bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data = Encoding.ASCII.GetString(bytes, 0, bytesRec);
ProcessData(data);
handler.Send(bytes);
break;
}
//Restart();
Console.ReadKey();
break;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/* void Restart()
{
i++;
StartListening();
}*/
public void ProcessData(string data)
{
switch (data)
{
}
}
}
Errors occur whenever i call listener.Accept();
In Unity, this worked fine. Anyone willing to help me here?
PS: I'm new to Networking, so i'm probably doing something stupid and i don't realise it.
You create 2 RasPi objects and call Initialize() and StartListening() on them individually. The second object won't have the same state as the first object that called Initialize() so StartListening() fails miserably. Instead, create one object and call both methods on it:
var rasPi = new RasPi();
rasPi.Initialize();
rasPi.StartListening();
I have a question with my UDP client server app.
I have a connection between the two. They both send data to each other. Only the server receives data from the client but not the other way around but the server is sending. What am I doing wrong?
using System;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace PewPewGame
{
class Client
{
UdpClient udpClient;
IPEndPoint RemoteIpEndPoint;
String serverIp;
String[] dataAray;
GameScreen gameScreen;
Player otherPlayer;
public Client(string serverIp, GameScreen gameScreen, Player otherPlayer)
{
this.gameScreen = gameScreen;
this.otherPlayer = otherPlayer;
udpClient = new UdpClient();
this.serverIp = serverIp;
}
public void clientThread()
{
udpClient = new UdpClient(serverIp,1002);
while (true)
{
RemoteIpEndPoint = new IPEndPoint(IPAddress.Parse(serverIp), 1002);
receiveData();
}
}
public void receiveData()
{
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
String clientData = Encoding.ASCII.GetString(receiveBytes);
dataAray = clientData.Split(',');
otherPlayer.x = Convert.ToInt32(dataAray[0]);
otherPlayer.y = Convert.ToInt32(dataAray[1]);
if (dataAray[3] == "1")
{
gameScreen.otherProjectile = new Projectile(Convert.ToInt16(dataAray[0]), Convert.ToInt16(dataAray[1]), 2, 4, 8, 8, dataAray[2]);
}
}
public void sendData(string data)
{
Byte[] senddata = Encoding.ASCII.GetBytes(data);
udpClient.Send(senddata, senddata.Length);
}
public static IPEndPoint CreateIPEndPoint(string endPoint)
{
string[] ep = endPoint.Split(':');
if (ep.Length < 2) throw new FormatException("Invalid endpoint format");
IPAddress ip;
if (ep.Length > 2)
{
if (!IPAddress.TryParse(string.Join(":", ep, 0, ep.Length - 1), out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
else
{
if (!IPAddress.TryParse(ep[0], out ip))
{
throw new FormatException("Invalid ip-adress");
}
}
int port;
if (!int.TryParse(ep[ep.Length - 1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port))
{
throw new FormatException("Invalid port");
}
return new IPEndPoint(ip, port);
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace PewPewGame
{
class Server
{
UdpClient udpClient;
IPEndPoint RemoteIpEndPoint;
String[] dataAray;
GameScreen gameScreen;
Player otherPlayer;
public Server(GameScreen gameScreen, Player otherPlayer)
{
this.gameScreen = gameScreen;
this.otherPlayer = otherPlayer;
}
public void serverThread()
{
udpClient = new UdpClient(1002);
while (true)
{
RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
receiveData();
}
}
public void sendData(string data)
{
Byte[] senddata = Encoding.ASCII.GetBytes(data);
udpClient.Send(senddata, senddata.Length);
}
public void receiveData()
{
Byte[] receiveBytes = udpClient.Receive(ref RemoteIpEndPoint);
try
{
String clientData = Encoding.ASCII.GetString(receiveBytes);
dataAray = clientData.Split(',');
otherPlayer.x = Convert.ToInt32(dataAray[0]);
otherPlayer.y = Convert.ToInt32(dataAray[1]);
if (dataAray[3] == "1")
{
gameScreen.otherProjectile = new Projectile(Convert.ToInt16(dataAray[0]), Convert.ToInt16(dataAray[1]), 2, 4, 8, 8, dataAray[2]);
}
}
catch { }
}
}
}
First of all: UDP knows no 'connection', so your first line is confusing.
Then you're using the UdpClient.Send(byte[], int) method to send data, but that expects a previous (confusingly named) call to Connect(string, int) or using the UdpClient constructor you're using for the client: new UdpClient(string, int).
I'm pretty sure your empty catch block (do not do this, and especially do not do this if something doesn't work as expected!) catches and swallows a SocketException per the remarks from [1]:
This overload sends datagrams to the remote host established in the Connect method and returns the number of bytes sent. If you do not call Connect before calling this overload, the Send method will throw a SocketException. If you receive a SocketException, use SocketException.ErrorCode to obtain the specific error code. Once you have obtained this code, you can refer to the Windows Sockets version 2 API error code documentation in MSDN for a detailed description of the error.
If you want to send datagrams to a different remote host, you must call the Connect method and specify the desired remote host. Use either of the other Send method overloads to send datagrams to a broadcast address.
So, in your server code:
1) Remove the empty catch block!
2) Use another udpClient.Send(byte[], int, IPEndPoint) overload that accepts the endpoint of the client - you get that via the reference you passed into Receive(ref IPEndPoint)
1: https://msdn.microsoft.com/en-us/library/08h8s12k(v=vs.110).aspx
I have searched many examples and tutorials and what not but I cant for the life of me figure out what im doing wrong here... If I send several messages to this server I made only the first is printed in the Console.Writeline command and the rest is never printed... I must be doing something fundametally wrong but I really cant find it ... :S
This is the server code:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms.VisualStyles;
namespace HL7_Manager
{
public class MonitorServer
{
private int _port;
private Socket _serverSocket;
private List<ClientObject> _clients;
public bool IsConnected { get; set; }
public MonitorServer(int port)
{
_port = port;
_clients = new List<ClientObject>();
}
public void StartListening()
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Thread listenThread = new Thread(new ThreadStart(ListenerThread));
listenThread.IsBackground = true;
listenThread.Start();
}
public void StopListening()
{
IsConnected = true;
_serverSocket.Close();
while (_clients.Count > 0)
{
_clients[0].KeepProcessing = false;
_clients[0].ClientSocket.Close();
_clients.RemoveAt(0);
}
}
private void ListenerThread()
{
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, _port));
_serverSocket.Listen(100);
Console.WriteLine("Listening on port 8000");
while (true)
{
Socket clientSocket = _serverSocket.Accept();
ClientObject client = new ClientObject();
client.KeepProcessing = true;
client.ClientSocket = clientSocket;
_clients.Add(client);
ParameterizedThreadStart ptStart = new ParameterizedThreadStart(ProcessClientThread);
Thread processThread = new Thread(ptStart);
processThread.IsBackground = true;
processThread.Start(client);
clientSocket = null;
client = null;
}
}
private void ProcessClientThread(object clientObj)
{
Console.WriteLine("Client connected");
ClientObject client = (ClientObject) clientObj;
Socket clientSocket = client.ClientSocket;
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int receiveCount = 0;
while (client.KeepProcessing)
{
try
{
receiveCount = clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
Console.WriteLine(Encoding.ASCII.GetString(buffer));
}
catch (Exception ex)
{
if (!client.KeepProcessing)
return;
Console.WriteLine(ex.Message);
}
}
clientSocket.Close();
_clients.Remove(client);
}
}
}
Here is the method you should definitely change and how to change it.
private void ProcessClientThread(object clientObj)
{
Console.WriteLine("Client connected");
ClientObject client = (ClientObject)clientObj;
Socket clientSocket = client.ClientSocket;
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int receiveCount = 0;
while (client.KeepProcessing)
{
try
{
receiveCount = clientSocket.Receive(buffer, 0, buffer.Length, SocketFlags.None);
if (receiveCount == 0)
break; //the client has closed the stream
var ret = Encoding.ASCII.GetString(buffer, 0, receiveCount);
Console.WriteLine(ret);
}
catch (Exception ex)
{
if (!client.KeepProcessing)
return;
Console.WriteLine(ex.Message);
}
}
clientSocket.Close();
_clients.Remove(client);
}
Check how many bytes you really received.
TCP is a streaming protocol this means that if you client is doing several sends of small messages right one after the other, you will receive them in one go at the receiver.
If there happens to be a null character in your receive buffer you might think you did not receive all those string, but actually you did.
Check this by inspecting how many bytes you received and by checking the buffer content.
If you made this mistake there might be some deeper problem in your code. The fact that TCP is streaming makes it a bit more complex
In a project there is a device that listens on a specific UDP port and answers to the senders port.
For the sender and receiver I want the system to choose a free port, so I have the following code:
[Please excuse the vast masses of code, but this is the smallest example to show what behaviour occurs]
Sending code:
public class UdpSender
{
public int Port = 0; // some initially random port
public UdpClient UdpServer { get; set; }
public UdpSender()
{
UdpServer = CreateUdpClient();
// save the portnumber chosen by system to reuse it
Port = ((IPEndPoint)(UdpServer.Client.LocalEndPoint)).Port;
}
private UdpClient CreateUdpClient()
{
if (UdpServer != null)
{
UdpServer.Close();
}
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, Port);
var udpServer = new UdpClient();
udpServer.ExclusiveAddressUse = false;
udpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpServer.Client.Bind(localEndPoint);
return udpServer;
}
public void Send(byte[] arr)
{
UdpServer = CreateUdpClient();
int remotePortNumber = 6565;
var remoteEndPoint = new IPEndPoint(IPAddress.Broadcast, remotePortNumber);
try
{
UdpServer.Send(arr, arr.Length, remoteEndPoint);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
UdpServer.Close();
}
}
Receiving code:
public class UDPListener
{
private static int portNumber;
private UdpClient udpClient = null;
public List<DeviceData> DeviceList = new List<DeviceData>();
public UDPListener(int port)
{
portNumber = port;
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
udpClient = new UdpClient();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(localEndPoint);
udpClient.Client.ReceiveBufferSize = 1 << 23;
}
public void StartListening()
{
this.udpClient.BeginReceive(Receive, new object());
}
private void Receive(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, portNumber);
byte[] bytes = udpClient.EndReceive(ar, ref ip);
string message = Encoding.ASCII.GetString(bytes);
DeviceList.Add(new DeviceData(message));
StartListening();
}
}
Bringing it together:
public class DeviceFinder
{
public IEnumerable<DeviceData> Find()
{
var sender = new UdpSender();
int port = sender.Port;
var listener = new UDPListener(port);
listener.StartListening();
sender.Send(new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6 });
System.Threading.Thread.Sleep(5000); // wait some time for answers
return listener.DeviceList;
}
}
The Receive method is never called with this approach. But in Wireshark, I can see an answer coming from the device.
What is wrong about this approach?
Before using this approach, I have used a fixed port and the call to CreateUdpClient was added also. Seems to have something to with that, but I cannot figure it out.
Before I just created a UdpClient with the fixed port just inside the receive / send method.
The previous version can be seen in this question. This works perfectly. But I fear if the fixed port is already in use, it does not work, hence this new approach.
Just specify zero as your own port number. The system will allocate one when you bind or send. The source port number will accompany the datagram to the peer, who should reply to it.