C# datagramsocket cannot receive - c#

I'm trying to make datagramsocket on UWP connect to UDPClient on desktop.
The odd thing is that datagramsocket never receive any message from UDPClient(event not work) unless send out message to UDPClient from datagramsocket first.
On the other hand, i'm sure my config(IP/PORT setting) is OK, because same config on UDPClients works OK.
Is there anything wrong with my code?(UWP CODE:)
private async void btn_start_Click(object sender, RoutedEventArgs e)//Listen
{
hostname = new HostName("192.168.1.5");
remotename = new HostName("192.168.1.5");
datagramsocket = new DatagramSocket();
datagramsocket.MessageReceived += Datagramsocket_MessageReceived;
try
{
await datagramsocket.BindServiceNameAsync("8010");
await datagramsocket.ConnectAsync(remotename, "8009");
}
catch(Exception err)
{
//show err message method
}
}
private async void Datagramsocket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{//read from args
//it works after click send button
}
//if i don't click btn_send first, then the MessageReceived event will never work
private async void btn_send_Click(object sender, RoutedEventArgs e)//send
{
string str_send = tb_send.Text;
byte[] str_byte = Encoding.Unicode.GetBytes(str_send);
IOutputStream outputstream = await datagramsocket.GetOutputStreamAsync(remotename, "8009");
DataWriter writer = new DataWriter(outputstream);
writer.WriteBytes(str_byte);
await writer.StoreAsync();
}

Related

Unable to listen UDP port in C#

I am trying to listen to UDP port 10086, store the data in the string "loggingEvent", combine the string and send it to the UDP port 51999. The UDP client 10086 is used to listen to port 10086 and the Udpclient 10087 is for sending the message to port 51999.
Although I can receive data in the UDP tool "Packet Sender", the C# code failed to listen to the message on port 10086. However, the port "10086", "10087" and "51999" really works, which can be found by using the command "net-stat -ano".
After debugging, I found that the thread exited at the line "var udpResult = await udpClient_listen.ReceiveAsync();", which confused me a lot. I have also tried non-asynchronous and still does not work. However, the "SendAsync" function works well.
In "CharacteristicPage.xaml.cs"
public static string udp_listener_ip;
public static int udp_listener_port;
public static int udp_client_port;
public static string udp_message;
public static UdpClient udpClient_listen;
public static UdpClient udpClient_send;
public static string loggingEvent;
private void button_udp_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
IPEndPoint endPoint_listen= new IPEndPoint(IPAddress.Parse(udp_listener_ip), 10086);
udpClient_listen = new UdpClient(endPoint_listen);
IPEndPoint endPoint1 = new IPEndPoint(IPAddress.Parse(udp_listener_ip), 10087);
udpClient_send = new UdpClient(endPoint1);
UDPListener();
}
private static async Task UDPListener()
{
try
{
while (true)
{
Debug.WriteLine("###############UDP listener task start###############");
var udpResult = await udpClient_listen.ReceiveAsync();
loggingEvent = Encoding.ASCII.GetString(udpResult.Buffer);
Debug.WriteLine("UDP listener received: " + loggingEvent);
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
var messageDialog = new MessageDialog(e.Message, "UDP connect failures");
await messageDialog.ShowAsync();
}
}
In "ObservableGattCharacteristic.cs"
private async void Characteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.Normal,
() =>
{
SetValue(args.CharacteristicValue);
});
var udpClient_send = Views.CharacteristicPage.udpClient_send;
var loggingEvent = Views.CharacteristicPage.loggingEvent;
try
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(Views.CharacteristicPage.udp_listener_ip), 51999);
DateTime foo = DateTime.Now;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
byte[] Payload = Encoding.UTF8.GetBytes(unixTime.ToString() + "," + loggingEvent + "," + ParseValue(value));
await udpClient_send.SendAsync(Payload, Payload.Length, endPoint);
Debug.WriteLine("UDP send message: " + Encoding.UTF8.GetString(Payload));
}
catch
{
Debug.WriteLine("FAILED to publish message!" );
}
}

Publish UWP Project

Hello I was trying to make two programs(server and client) on one machine. I did it with WPF and then I tried to do it with UWP, but I didn't succeed. The problem is that the listener in the server is waiting for a connection, but it never comes. This only happens when I try to do the connection from two separate projects.
If I do it in one project everything works fine. I saw somewhere that it is not possible to run the server and client form one machine with UWP, but the information was not so good explained.
So my question is, is it possible to make two separate projects with UWP for server and client on one computer and if not how can I test the programs(Do I need another computer to test it or there is some other way to do it).
And can someone tell me if there is a possible way to publish my project like the option from Console Applications, so that I can send my client to another computer maybe and try then. All I could find on the internet is how to publish your Apps to the Microsoft Store.
Server
public sealed partial class MainPage : Page
{
string port = "11000";
string hostv4 = "127.0.0.1";
StreamSocketListener server;
public MainPage()
{
InitializeComponent();
StartServer();
}
private async void StartServer()
{
HostName name = new HostName(hostv4);
server = new StreamSocketListener();
server.ConnectionReceived += this.Receive;
await server.BindEndpointAsync(name, port);
Chat.Content += ("server is listening...\n");//chat is a ScrollViewer where I show the received messsges
}
private async void Receive(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
string receivedMsg;
using (var sr = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
{
receivedMsg = await sr.ReadLineAsync();
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Chat.Content += (string.Format("server received the request: \"{0}\"\n", receivedMsg)));
}
}
Client
public sealed partial class MainPage : Page
{
string port = "11000";
string hostv4 = "127.0.0.1";
StreamSocket client;
public MainPage()
{
this.InitializeComponent();
Connect();
}
private async void Connect()
{
client = new StreamSocket();
HostName name = new HostName(hostv4);
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Chat.Content += (string.Format("client trying to connect...\n")));
await client.ConnectAsync(name, port);
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Chat.Content += (string.Format("client connected\n")));
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string request = Input.Text; //Input is the name of my TextBox
using (Stream outputStream = client.OutputStream.AsStreamForWrite())
{
using (var sw = new StreamWriter(outputStream))
{
await sw.WriteLineAsync(request);
await sw.FlushAsync();
}
}
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Chat.Content += (string.Format("client sent request: {0}\n", request)));
}
I also have enabled Internet(Client & Server) and Private Networks(Client & Server) from the Capabilities

Using UdpClient, how do you retry UdpClient.Connect() until it succeeds?

My client/server programs work well with each other, but only when the server is up and running before my client starts. If the client fails to connect on the first try, I can't get it to try again.
Here's my Client's connect method.
public void connect()
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
bool connected = false;
while (!connected)
{
try
{
Console.WriteLine("IN CONNECTED");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
connected = true;
Console.WriteLine("RECEIVED INIT");
listen(server_ip);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
What I was hoping to see is the udp_client.Connect(server_ip) to loop until I received that "INIT" message from the server.
As it currently stands, there is no loop. It seems to get stuck on udp_client.Receive(ref server_ip).
Any help would be appreciated!
This is pseudoCode - you will have to move somethings to class scope to allow future send/receives (which you'd do using a different method). This is only designed to show you how to connect when the connection blocks:
bool isClientConnected = false;
var connector = new System.ComponentModel.BackgroundWorker();
public void connectToUDP(){
connector.DoWork+= connect;
connector.RunWorkerAsync();
}
private void connect(object sender, DoWorkEventArgs e)
{
IPAddress server_address = IPAddress.Parse("127.0.0.1");
IPEndPoint server_ip = new IPEndPoint(server_address, 5685);
Console.WriteLine("2");
try
{
Console.WriteLine("Waiting for server...");
udp_client.Connect(server_ip);
byte[] send_data = Encoding.ASCII.GetBytes("INIT");
udp_client.Send(send_data, send_data.Length);
byte[] received_bytes = udp_client.Receive(ref server_ip);
string received_data = Encoding.ASCII.GetString(received_bytes);
if (received_data == "INIT")
{
isClietConnected = true;
Console.WriteLine("now connected");
listen(server_ip);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public bool sendReceiveUDP(string send){
if(!isClientConnected){
return false;
}
//perform send
return true;
}
You would then maintain the connected session using class scope and send/receive using a different method. This is for connect only since you only need to do it once.
How you set something like this up:
private bool isConnected = false();
private bool send(){
if(!isConnected){
connect();
}
//send
}
private bool connect(){
if(!isConnected){
//launch connection thread
}
}
private delegate void onNewReceive(string message);
public event onNewReceive onNewReceiveEvent;
public void fireEvent(string message){
onNewReceiveEvent.Invoke(message);
}
private void waitForData(object sender, DoWorkEventArgs e){
//this is the backgroundworker
while(true){
receive();
fireEvent(message);
}
}
Then, subscribe to the onNewREceivedEvent in another class and process the inbound message. onNewReceivedEvent += processInboundMEsasage();
This is all psuedocode and "brain compiled" (creit to others) so it's only meant for demonstrations. Without intellisense, I'm lost.

TCPIP connection in c# and data sending/receiving in another threads

I have a problem with my TCPIP connection Form programm.
I have a code, where I'm trying to send and receive some data from server.
The main problem of my app is how to reconcile some threads:
myListenThread - to listening data from server
myReadStreamThread - to read data from server
System.Threading.Thread - main thread eg. to write data to server
captureThread - to do another things like capturing images from camera
Part of my code:
private void buttonConnect_Click(object sender, EventArgs e)
{
try
{
Connect();
Connected = true;
this.myListenThread = new Thread(new ThreadStart(Listen));
this.myListenThread.Start();
}
catch
{
MessageBox.Show("Invalid host! Try again.");
}
}
private void Listen()
{
this.myReadStreamThread = new Thread(new ThreadStart(ReadStream));
this.myReadStreamThread.Start();
while (Connected)
{
if (!myReadClient.Connected)
{
Connect();
}
}
}
private void Connect()
{
IPAddress IP = IPAddress.Parse(textboxIP.Text);
int PORT = Convert.ToInt32(textboxPORT.Text);
this.myReadClient = new TcpClient();
this.myReadClient.Connect(IP, PORT);//SOMETIMES HERE'S AN ERROR
this.myStream = this.myReadClient.GetStream();
Properties.Settings.Default.IP = Convert.ToString(IP);
Properties.Settings.Default.PORT = Convert.ToString(PORT);
Properties.Settings.Default.Save();
}
private void ReadStream()
{
while (true)
{
try
{
this.myReadBuffer = new byte[this.myReadClient.ReceiveBufferSize];
this.myBufferSize = myStream.Read(myReadBuffer, 0, this.myReadClient.ReceiveBufferSize);
if (myBufferSize != 0)
{
this.myString = Encoding.ASCII.GetString(myReadBuffer);
//myDelegate myDel;
//myDel = new myDelegate(Print);
//richtextboxRead.Invoke(myDel);
}
}
catch
{
break;
}
}
}
All is working correct when I'm connecting to server, but when I want to send some string the problem appears because of threads.
I decided to send string, by clicking Button3 and waiting until I receive string "1" from server using while loop:
private void button3_Click(object sender, EventArgs e)
{
this.captureThread = new Thread(new ThreadStart(() => this.newGame()));
this.captureThread.Start();
}
private bool newGame()
{
string command = "12345abc";
if (Connected)
{
WriteStream(command);
}
while (myBufferSize == 0 && myString !="1") { }
Thread.Sleep(2000);
...//doing other things
}
private void WriteStream(string command)
{
Connect();
this.myWriteBuffer = Encoding.ASCII.GetBytes(command);
this.myStream.Write(this.myWriteBuffer, 0, command.Length);
}
And the problem with connection and data send/receive problem appears, when it should write my string "command" - it doesn't react. MyBufferSize is always 0 and myString is always null. Sometimes an Error about connection appears when I click Button3 (assigned in code). I think it is because in captureThread I can't see any data from another threads. How to solve it?

UDP Connection Between Client and Server

Here is the server code of my program this is working, but after it sends data it gets stuck. I need it to be refreshed and ready for sending data again.
Server code:
private void button1_Click(object sender, EventArgs e) {
try {
String text = textBox1.Text;
UdpClient udpc = new UdpClient(text,8899);
IPEndPoint ep = null;
while (true) {
MessageBox.Show("Name: ");
string name = textBox2.Text;
if (name == "") break;
byte[] sdata = Encoding.ASCII.GetBytes(name);
udpc.Send(sdata, sdata.Length);
if (udpc.Receive(ref ep)==null) {
MessageBox.Show("Host not found");
} else {
byte[] rdata = udpc.Receive(ref ep);
string job = Encoding.ASCII.GetString(rdata);
MessageBox.Show(job);
}
}
} catch {
MessageBox.Show("Error Restarting");
}
Client code:
private void button1_Click(object sender, EventArgs e) {
try {
UdpClient subscriber = new UdpClient(8899);
IPAddress addr = IPAddress.Parse("127.0.0.2");
subscriber.JoinMulticastGroup(addr);
IPEndPoint ep = null;
for (int i = 0; i < 1; i++) {
byte[] pdata = subscriber.Receive(ref ep);
string strdata = Encoding.ASCII.GetString(pdata);
MessageBox.Show(strdata);
textBox1.Text = strdata;
pass = strdata;
}
subscriber.DropMulticastGroup(addr);
} catch {
Refresh();
MessageBox.Show("Not Found");
}
}
The Server can send data to one client . I want to send one client at a time. But after sending the data, the server gets stuck.
I need it do refresh and send data again for a client.
If I understood your code, from the server your sending data, then waiting for an answer. In the client, your just getting the data, but not sending anything back. And unless you provide timeout to the socket, it will wait indefinitely until something arrives.
You shouldn't use udpc.Receive() in the main UI thread (inside button1_Click). If you do, your aplication will hang until something arrives. Using a timeout isn't a solution either. The application will just hang until the timeout expires. Instead You must use a multiple threads. You can do so by using BeginReceive instead of Receive or by explicitly creating a new thread and using Receive there. If you google for "asynchronous udp sockets in c#" or something like that, then you will find plenty of examples on how to set it up correctly.
The udpc.Receive() Method on your server side, will Block Until a datagram receive from client.
UDP in not reliable. it means that server doesnt expect any ACK from other side. so you can simply remove this part of code. or if you need to ensure message arrival, run a separate thread for each client as follow:
private void button1_Click(object sender, EventArgs e) {
System.Threading.Thread Server_thread = new Thread(My_Send_Function);
Server_thread .Start();
}
private void My_Send_Function() {
try {
String text = textBox1.Text;
UdpClient udpc = new UdpClient(text,8899);
IPEndPoint ep = null;
while (true) {
MessageBox.Show("Name: ");
string name = textBox2.Text;
if (name == "") break;
byte[] sdata = Encoding.ASCII.GetBytes(name);
udpc.Send(sdata, sdata.Length);
if (udpc.Receive(ref ep)==null) {
MessageBox.Show("Host not found");
} else {
byte[] rdata = udpc.Receive(ref ep);
string job = Encoding.ASCII.GetString(rdata);
MessageBox.Show(job);
}
}
} catch {
MessageBox.Show("Error Restarting");
}
}

Categories