I am trying to write a graphical C# program that can communicate with my Node.js server.
I am using UdpClient class and I am able to send some messages to the server.
However, I don't know how to receive UDP packages from the server.
JavaScript and Windows Form Widgets are event-driven, but UdpClient class in C# doesn't have any convenient events related to data reception.
Also, I don't know where to put the code of package reception. Most of online examples are console program and my program is GUI based.
I want my program to continuously listen at a port and when a package comes in, the program can capture the package and display its content in a TextBox.
Any suggestions ?
You can listen to a port asynchronously using BeginReceive. It works in GUI applications too - just remember to send the data to the UI thread before interacting with the UI.
This example is from a WinForms application. I've put a multiline textbox on the form called txtLog.
private const int MyPort = 1337;
private UdpClient Client;
public Form1() {
InitializeComponent();
// Create the UdpClient and start listening.
Client = new UdpClient(MyPort);
Client.BeginReceive(DataReceived, null);
}
private void DataReceived(IAsyncResult ar) {
IPEndPoint ip = new IPEndPoint(IPAddress.Any, MyPort);
byte[] data;
try {
data = Client.EndReceive(ar, ref ip);
if (data.Length == 0)
return; // No more to receive
Client.BeginReceive(DataReceived, null);
} catch (ObjectDisposedException) {
return; // Connection closed
}
// Send the data to the UI thread
this.BeginInvoke((Action<IPEndPoint, string>)DataReceivedUI, ip, Encoding.UTF8.GetString(data));
}
private void DataReceivedUI(IPEndPoint endPoint, string data) {
txtLog.AppendText("[" + endPoint.ToString() + "] " + data + Environment.NewLine);
}
Related
Hello everyone I am very new to Visual Studio, C# programming, and Windows Form Applications.
My need is very simple - I want to create my own small program to listen to data being sent by a GPS device over UDP. I do not need to communicate, just listen and see the data on the screen!
Something that works exactly the same as this :
http://sockettest.sourceforge.net/ (see 'UDP' tab)
My GPS device has an IP of 192.168.1.1 and sends a sting of numbers every 1 second, continuously, transmitting on UDP 25.255.255.255:5017.
All the examples on the internet seems to focus on 2-way communicate, client and server chat windows etc. There is a lot of confusing terminology like synchronous and a-synchronous, client, server, UDP, TCP, binding.
I just want an even more simplified program than the above example, where I can type in the port number 5017, click Start Listening, and then straight away works!
All advice and code examples very gratefully received!!
Many thanks,
Jon
I now have it working, and can receive data in a textbox in the UI!
I use button_start_Click to open the port and start receiving. However, I cannot get button_stop_Click to work. How can you stop/close/disconnect/endReceive using button click?
public Form1()
{
InitializeComponent();
}
private void button_start_Click(object sender, EventArgs e)
{
Client = new UdpClient(Convert.ToInt32(textBox_port.Text));
Client.BeginReceive(DataReceived, null);
}
private void DataReceived(IAsyncResult ar)
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, Convert.ToInt32(textBox_port.Text));
byte[] data;
try
{
data = Client.EndReceive(ar, ref ip);
if (data.Length == 0)
return; // No more to receive
Client.BeginReceive(DataReceived, null);
}
catch (ObjectDisposedException)
{
return; // Connection closed
}
// Send the data to the UI thread
this.BeginInvoke((Action<IPEndPoint, string>)DataReceivedUI, ip, Encoding.UTF8.GetString(data));
}
private void DataReceivedUI(IPEndPoint endPoint, string data)
{
txtLog.AppendText("[" + endPoint.ToString() + "] " + data + Environment.NewLine);
}
private void button_stop_Click(IAsyncResult ar) // NOT WORKING!! AGH!
{
IPEndPoint ip = new IPEndPoint(IPAddress.Any, Convert.ToInt32(textBox_port.Text));
byte[] data;
data = Client.EndReceive(ar, ref ip);
Client.Close();
}
Run the same code in background worker and then you can cancel the background worker anytime using backgroundworker.cancelasync().
Hope this helps.
I am currently creating an Unity Android application (GearVR) that could receive UDP packets send with broadcast on the Wi-Fi.
Unfortunately I can't receive any packet in my application.
Here is the script which I attached to a 3d game object.
public class UDPSceneScript : MonoBehaviour {
Thread udpListeningThread;
Thread udpSendingThread;
public int portNumberReceive;
UdpClient receivingUdpClient;
private void initListenerThread()
{
portNumberReceive = 5000;
Console.WriteLine("Started on : " + portNumberReceive.ToString());
udpListeningThread = new Thread(new ThreadStart(UdpListener));
// Run in background
udpListeningThread.IsBackground = true;
udpListeningThread.Start();
}
public void UdpListener()
{
receivingUdpClient = new UdpClient(portNumberReceive);
while (true)
{
//Listening
try
{
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
//IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Broadcast, 5000);
// Blocks until a message returns on this socket from a remote host.
byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
if (receiveBytes != null)
{
string returnData = Encoding.ASCII.GetString(receiveBytes);
Console.WriteLine("Message Received" + returnData.ToString());
Console.WriteLine("Address IP Sender" + RemoteIpEndPoint.Address.ToString());
Console.WriteLine("Port Number Sender" + RemoteIpEndPoint.Port.ToString());
if (returnData.ToString() == "TextTest")
{
//Do something if TextTest is received
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
void Start()
{
initListenerThread();
}
}
With the program SocketTest 3.0, I send "TextTest" to the address 255.255.255.255, port 5000
(I also tried by targeting directly the IP of the smartphone, it didn't work either)
Thanks in advance
Ran a quick test on your code and came to conclusion that your client code is fine. Replace all Console.WriteLine with Debug.Log and your will receive the data you are broadcasting. Console.WriteLine doesn't display anything in Unity's console.
If the problem is still there, please understand that some OS will block you from broadcasting to 255.255.255.255. If this is the case then get the IP of the device you are broadcasting from and replace the last octet with 255. Broadcast to that IP Address and that will also work just like 255.255.255.255.
For example, if your IP is 192.168.1.13, replace 13 with 255. You should broadcast to 192.168.1.255 in this case.
Finally, put the code below in your client script to make sure you kill that Thread when you click the Stop button in the Editor or you will have many problems during development.
void OnDisable()
{
if (udpListeningThread != null && udpListeningThread.IsAlive)
{
udpListeningThread.Abort();
}
receivingUdpClient.Close();
}
I'm working to make a Client/Server Application in C# using winsock Control. I done every thing in that but i stuck the place of sending data from client to server. In my program server always listen the client using the ip and port. I send the data from the client to server.
1)When click the Listen button on the server form it open the server where client is connect.
2)In Client form 1st i click the connect button for that the server is connected Gives an message (Connect Event: ip) for this message we easly know that the client is connected to the server.
3)Then we enter some data in the Send Data text Box then click Send Button to send the data to server and also save in client.
Code Below:
SERVER:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace Server
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const string DEFAULT_SERVER = "ip";
const int DEFAULT_PORT = 120;
System.Net.Sockets.Socket serverSocket;
System.Net.Sockets.SocketInformation serverSocketInfo;
public string Startup()
{
IPHostEntry hostInfo = Dns.GetHostByName(DEFAULT_SERVER);
IPAddress serverAddr = hostInfo.AddressList[0];
var serverEndPoint = new IPEndPoint(serverAddr, DEFAULT_PORT);
serverSocket = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
serverSocket.Bind(serverEndPoint);
return serverSocket.LocalEndPoint.ToString();
}
public string Listen()
{
int backlog = 0;
try
{
serverSocket.Listen(backlog);
return "Server listening";
}
catch (Exception ex)
{
return "Failed to listen" + ex.ToString();
}
}
public string ReceiveData()
{
System.Net.Sockets.Socket receiveSocket;
byte[] buffer = new byte[256];
receiveSocket = serverSocket.Accept();
var bytesrecd = receiveSocket.Receive(buffer);
receiveSocket.Close();
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
return encoding.GetString(buffer);
}
private void Listen_Click(object sender, EventArgs e)
{
string serverInfo = Startup();
textBox1.Text = "Server started at:" + serverInfo;
serverInfo = Listen();
textBox1.Text = serverInfo;
//string datatosend = Console.ReadLine();
//SendData(datatosend);
serverInfo = ReceiveData();
textBox1.Text = serverInfo;
//Console.ReadLine();
}
private void winsock_DataArrival(object sender, AxMSWinsockLib.DMSWinsockControlEvents_DataArrivalEvent e)
{
ReceiveData();
Listen();
}
private void winsock_ConnectEvent(object sender, EventArgs e)
{
Listen();
}
}
}
This all are work perfectly But here my problem is that i get data form the client to server at only one time. When i send data again from the client to the server its not working and gives me some Message like
Additional information: Only one usage of each socket address
(protocol/network address/port) is normally permitted
In the server form
serverSocket.Bind(serverEndPoint);
Please someone help me to solve my problem.
Thank you.
Try this. It helps you
delegate void AddTextCallback(string text);
public Form1()
{
InitializeComponent();
}
private void ButtonConnected_Click(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
}
private void ServerHandler(object state)
{
TcpListener _listner = new TcpListener(IPAddress.Parse("12.2.54.658"), 145);
_listner.Start();
AddText("Server started - Listening on port 145");
Socket _sock = _listner.AcceptSocket();
//AddText("User from IP " + _sock.RemoteEndPoint);
while (_sock.Connected)
{
byte[] _Buffer = new byte[1024];
int _DataReceived = _sock.Receive(_Buffer);
if (_DataReceived == 0)
{
break;
}
AddText("Message Received...");
string _Message = Encoding.ASCII.GetString(_Buffer);
AddText(_Message);
}
_sock.Close();
AddText("Client Disconnected.");
_listner.Stop();
AddText("Server Stop.");
}
private void AddText(string text)
{
if (this.listBox1.InvokeRequired)
{
AddTextCallback d = new AddTextCallback(AddText);
this.Invoke(d, new object[] { text });
}
else
{
this.listBox1.Items.Add(text);
}
}
I'm also have the same problem like you on last month but i solve that using this Receive multiple different messages TcpListener C# from stackoverflow. This helps me lot hope it helps to solve your problem also.
I'm not 100% sure you understand TCP sockets so here goes.
When you use a TCP listener socket you first bind to a port so that clients have a fixed, known point to connect to. This reserves the port for your socket until you give it up by calling Close() on that socket.
Next you Listen in order to begin the process of accepting clients on the port you bound to. You can do both this and the first step in one but as you haven't I haven't here.
Next you call Accept(). This blocks (halts execution) until a client connects and then it returns a socket which is dedicated to communication with that client. If you want to allow another client to connect, you have to call Accept() again.
You can then communicate with your client using the socket that was returned by Accept() until you're done, at which point you call Close() on that socket.
When you're done listening for new connections you call Close() on your listener socket.
However when you press your listen button the following happens:
You bind correctly, you begin listening correctly and then your call to ReceiveData() blocks on the Accept call until a client is received. You then receive some data (though this is TCP so that might not be the whole data!) and then you instantly close the connection to your client.
I presume to get the error you're getting you must then press listen again on your server. This therefore restarts the whole listener socket and when you get to bind to the port the second time your previous listener is still bound to it and thus the call fails because something's already allocated on that port.
Solution wise you need to keep the socket returned from the Accept() call open until you're done with it. Have the client handle the close by calling the Shutdown() method on their socket or establish some convention for marking the end of communication.
You're also going to run into trouble when you try and have multiple users connected and so at some point you're either going to require threads or some asynchronous sockets but I feel that's out the scope of this question.
I suggest you do not use AxMSWinsockLib.. Have a look at socket example given here where it shows how to create a client socket and server socket - https://msdn.microsoft.com/en-us/library/kb5kfec7(v=vs.110).aspx AND this one - https://msdn.microsoft.com/en-us/library/6y0e13d3(v=vs.110).aspx
I've got the client/server working, the client is sending data to the server with no issues, and right now I just have a RichTextBox displaying the data received from the client.
What I would like to do is have the server display the data received in the RichTextBox, and then SendKeys the message to the active window (the server will be minimized to the system tray while this is happening).
CLIENT PORTION:
using System.Net;
using System.Net.Sockets;
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("MyIP"), 8888);
public Console()
{
InitializeComponent();
client.Connect(serverEndPoint);
}
private void SendMessage(string msg)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
///...
private void button1_Click(object sender, EventArgs e)
{
SendMessage("T");
}
Now, all of that seems fine to me, as my server app is receiving the message just fine. My problem is on the server side. I can't seem to get the SendKeys function to work properly, so I've commented it out of my code snippet:
SERVER PORTION:
using System.Net;
using System.Net.Sockets;
using System.Threading;
private TcpListener tcpListener;
private Thread listenThread;
private int connectedClients = 0;
private delegate void WriteMessageDelegate(string msg);
public Form1()
{
InitializeComponent();
Server();
}
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
connectedClients++;
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (true)
{
bytesRead = 0;
try
{
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
break;
}
if (bytesRead == 0)
{
connectedClients--;
lblNumberOfConnections.Text = connectedClients.ToString();
break;
}
ASCIIEncoding encoder = new ASCIIEncoding();
//Write message in RichTextBox and send keystrokes to active window
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
// SendKeys.Send(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
}
As I said, it displays the data in the textbox just fine, but what I'd like to do as well (and the main purpose of this app) is to take the message received from the client, and add it to a SendKeys (or similar), and simulate those key presses in the active window. I just can't seem to figure out how to do that though...
Also, since I used SendMessage in my client app, and some of the keypresses I need to send to the active window contain modifiers, I just sent them as a text message to my server (ie. for the command CTRL-T, I literally sent the text "CTRL-T" to my server app), I was hoping I could do something along the lines of this:
If message is received as a single keystroke, just use SendKeys (ie. SendKeys.Send("T");)
If message is received as a keystroke with a modifier (ie. CTRL-T) change it to proper SendKeys modifier (ie. SendKeys.Send("{^T}");)
I don't have a problem assigning the events for commands with modifiers manually, since there is only going to be two commands being received that use modifiers, but I'm not sure how to implement that part either.
I would like my server to send the string received from my client (which I believe is msg) and send it to the active window as a keypress. I would like to add an "IF" statement to the code so that if the server receives a certain message (the commands with modifiers; which are all known commands, so I could program which commands to listen for), it sends a specified keypress(depending on which command was received) to the active window.
UPDATE:
I've managed to figure out how to use SendKeys to send the data from the client to the active window on the server machine. It was my original placement of the SendKeys command that needed changing. I've updated it as follows:
//Write message in RichTextBox
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
SendKeys.Send(msg);
}
Now my problem is back to me being inexperienced with C#.
I'm not sure of the proper way to implement the IF statement I need to catch the string before I send it to the active window. I need to use an IF statement to catch the string first, because some of the messages coming from the server aren't formatted as proper keystrokes.
Basically, what I'd like to do is have anything that is just a single character slip by my IF statement, and look for two particular messages.
The two messages I need to intercept are "CTRL-T" and "CTRL-H".
I don't know the proper formatting, since this is my first C# app, and I'm learning as I go, but my idea is to tell the program as follows:
If the message contained in the string is "CTRL-T" then SendKeys.Send("{^T}");
If the message contained in the string is "CTRL-H" then SendKeys.Send("{^H}");
If it is anything else then SendKeys.Send(msg);
Does that sound like the proper way to accomplish what I've explained here?
EDIT: I've attempted to figure out how to format my IF statement, but it's obviously wrong:
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
SendKeys.Send("{^T}");
}
else if (msg.Equals("CTRL-H"))
{
SendKeys.Send("{^H}");
}
else
{
SendKeys.Send(msg);
}
I tested the first IF statement by replacing "{^T}" with "TEST" and it sends the word TEST to notepad with no issues, but when I put in "{^T}", as soon as I hit the button to send that command, my server crashes.
The same thing happens for trying to send "{^H}"
Anyone have an idea what I'm doing wrong here?
I guess I'll answer my own question, since I've got the basic functionality that I was looking for now.
Basically, I wanted to accept a message from a client app, and display it in a text box on my server app, and then convert that message to simulated keypresses in the active window.
Before sending the keypresses to the window, I had to make sure that only the single digit keypresses were being sent to the active window immediately, and the other two known commands that needed modifiers attached to them were caught before being sent, and modified so they would act as modified keypresses, and not sent as a chunk of text (ie. "CTRL-T") instead of the actual "CTRL" button+T button
//Write message in RichTextBox
string msg = encoder.GetString(message, 0, bytesRead);
WriteMessage(msg);
}
tcpClient.Close();
}
private void WriteMessage(string msg)
{
if (this.rtbServer.InvokeRequired)
{
WriteMessageDelegate d = new WriteMessageDelegate(WriteMessage);
this.rtbServer.Invoke(d, new object[] { msg });
}
else
{
this.rtbServer.AppendText(msg + Environment.NewLine);
// SEND KEYSTROKES TO ACTIVE WINDOW
if (msg.Equals("CTRL-T"))
{
SendKeys.Send("^T");
}
else if (msg.Equals("CTRL-H"))
{
SendKeys.Send("^H");
}
else
{
SendKeys.Send(msg);
}
I want to preface this by saying my understanding of UDP Broadcasting and Multicasting is very limited. This is my first project working on this.
I have a C# desktop client running on a machine and a Windows phone 7 app.
The WP7 app is supposed to send a UDP broadcast over the network and the desktop client is supposed to listen for a UDP Multicast and respond accordingly. This is just meant for simple machine discovery over the network to find machines running the desktop client.
C# Desktop Client Code
public class ConnectionListener
{
private const int UDP_PORT = 54322;
private static readonly IPAddress MULTICAST_GROUP_ADDRESS = IPAddress.Parse("224.0.0.1");
private UdpClient _listener;
public ConnectionListener()
{
_listener = new UdpClient(UDP_PORT, AddressFamily.InterNetwork);
_listener.EnableBroadcast = true;
_listener.JoinMulticastGroup(MULTICAST_GROUP_ADDRESS);
_listener.BeginReceive(ReceiveCallback, null);
}
private void ReceiveCallback(IAsyncResult result)
{
IPEndPoint receiveEndpoint = new IPEndPoint(IPAddress.Any, UDP_PORT);
byte[] receivedBytes = _listener.EndReceive(result, ref receiveEndpoint);
byte[] response = Encoding.UTF8.GetBytes("WPF Response");
_listener.BeginSend(response, response.Length, receiveEndpoint, SendCallback, null);
}
private void SendCallback(IAsyncResult result)
{
int sendCount = _listener.EndSend(result);
Console.WriteLine("Sent Count is: " + sendCount);
}
}
The WP7 Server code:
public class MachineDetector
{
public const int UDP_PORT = 54322;
private const string MULTICAST_GROUP_ADDRESS = "224.0.0.1";
UdpAnySourceMulticastClient _client = null;
bool _joined = false;
private byte[] _receiveBuffer;
private const int MAX_MESSAGE_SIZE = 512;
public MachineDetector()
{
_client = new UdpAnySourceMulticastClient(IPAddress.Parse(MULTICAST_GROUP_ADDRESS), UDP_PORT);
_receiveBuffer = new byte[MAX_MESSAGE_SIZE];
_client.BeginJoinGroup(
result =>
{
_client.EndJoinGroup(result);
_client.MulticastLoopback = false;
SendRequest();
}, null);
}
private void SendRequest()
{
byte[] requestData = Encoding.UTF8.GetBytes("WP7 Multicast");
_client.BeginSendToGroup(requestData, 0, requestData.Length,
result =>
{
_client.EndSendToGroup(result);
Receive();
}, null);
}
private void Receive()
{
Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length);
_client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length,
result =>
{
IPEndPoint source;
_client.EndReceiveFromGroup(result, out source);
string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length);
string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived);
Console.WriteLine(message);
Receive();
}, null);
}
}
I am able to receive data with the desktop client, but the WP7 app doesn't seem able to receive the response. I've been banging my head on this for a while now and don't know where else to look. Any help would be great.
So, any suggestions why the WP7 app isn't receiving a response?
I think the issue is with ConnectionListener:ReceiveCallback in C# Desktop Client.
_listener.BeginSend(response, response.Length,
receiveEndpoint, SendCallback, null);
Instead call
_listener.BeginSend(response, response.Length,
SendCallback, null);
This will cause the message to be sent to the multicast address. For further help with this refer to How to: Send and Receive Data in a Multicast Group for Windows Phone.
WP7 needs to multicast to the network in order to efficiently reach all desktop clients in one sweep. For the client response, the only intended destination is WP7. As such, a multicast has no real advantage here (as the desktop clients tuned into the multicast will effectively be ignoring it).
Instead, you could use receiveEndpoint populated by the call to EndReceive in ConnectionListener:ReceiveCallback to send a unicast response to the WP7 server. This is recommended consideration for creating multicast applications at MSDN.
This way WP7 no longer needs to join the multicast group for incoming multicast and the desktop client needn't send a multicast to respond.