Issues with async receiving UDP Unicast packets in Windows Phone 7 - c#

I'm trying to get my Windows Phone 7 Mango app to listen to incoming UDP packets but having a heck of a time. I have the new Beta 2 refresh of the Windows Phone 7.1 SDK and dev tools installed. Any deviation I try from this MSDN sample results in a SocketException 10022, "An invalid argument was supplied".
My code is pasted below. I have been trying to adapt the code I found on this stackoverflow post but to no avail. This line generates the exception when its reached:
synchronous = m_udpSock.ReceiveFromAsync(udpRecvArg);
I'm hoping someone here can help identify what's going wrong. I'm calling "StartUnicastListen()" when the user presses a button. m_udpSock is previously defined as a class variable and set to null. Per the "Remarks" section of the ReceiveFromAsync() MSDN page, I've set all of the required properties and events.
private void StartUnicastListen()
{
m_udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
SocketAsyncEventArgs udpRecvArg = new SocketAsyncEventArgs();
udpRecvLoopStart(udpRecvArg);
}
private void udpRecvLoopStart(SocketAsyncEventArgs udpRecvArg)
{
byte[] udpRecvBuffer = new byte[2048];
udpRecvArg.SetBuffer(udpRecvBuffer, 0, udpRecvBuffer.Length);
udpRecvArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 11100);
udpRecvArg.Completed += new EventHandler<SocketAsyncEventArgs>(udpRecvArg_Completed);
udpRecv(udpRecvArg);
}
private void udpRecv(SocketAsyncEventArgs udpRecvArg)
{
bool synchronous = false;
try {
synchronous = m_udpSock.ReceiveFromAsync(udpRecvArg);
} catch (SocketException e) {
Log("recvUdp()\n" + e.SocketErrorCode + "\n" + e.ToString(), false);
return;
} if (synchronous)
udpRecvArg_Completed(this, udpRecvArg);
}
void udpRecvArg_Completed(object sender, SocketAsyncEventArgs udpRecvArg) {
EndPoint udpEp = udpRecvArg.RemoteEndPoint;
string msg = Encoding.UTF8.GetString(udpRecvArg.Buffer, udpRecvArg.Offset, udpRecvArg.BytesTransferred);
Log(udpEp + " " + msg,false);
udpRecv(udpRecvArg);
}
There's such limited documentation the proper usage of ReceiveFromAsync()--which seems to be the only option for this on WP7--and on System.Net.Sockets in Windows Phone 7 in general right now.
Thanks in advance for any help you can provide.

I had this same problem, but here is the solution that I came up with. As wilbur4321 said, you have to send something to the socket first. Also, not only do you need to just call SendToAsync and forget about it, you must wait for it (max of 1 second seems to work for me).
I do not know why you are required to do this, but sending something (I just send 1 byte: 0xFF) seems to do the trick.

Have you seen the sample at http://msdn.microsoft.com/en-us/library/hh202864(v=VS.92).aspx#Y4537?
Given that TCP sockets are client-only in Mango, I wonder is UDP sockets might only work after something has been sent? I would suggest trying that. If that doesn't work, could you post your entire project on dropbox or the like, and I'll look at it.
Thanks,
--randy

I found that a strange thing in that "Win7 UDP server" sample
that is the server-side UDP socket doesn't "Bind"
in my experiment, call "ReceiveFromAsync" on a socket which doesn't bind, "invalid argument" exception is throw. After binding before "ReceiveFromAsync", at least "ReceiveFromAsync" won't throw "invalid argument" exception.
My codes is similar to yours, but there is still some problems. it seems that, I call "ReceiveFromAsync" once, but the OS fire the event callbacks twice, which cause very serious race condition.
There is so few sample, documents about "UDP + SocketAsyncEventArgs". Maybe I have to revert back to using "BeginReceiveFrom".

You need to call ReceiveFormAsync() from the Completed event of SendTAsync()..Otherwise, you will get this exception..

Related

How to bind web socket to events in .NET C#

I am writing a plugin for the Elgato Stream Deck. The Stream Deck uses a web socket for communication with plugins. I am trying to write my plugin as a console app in C#. The "compiled plugin" example provided by Elgato is broken (this GitHub issue points to one problem, and there appear to be more) and does not appear to run - so I have been digging through the code to make sense of it and translate it to C# without using Visual Studio debugging. I did find this, however (link to code file on GitHub):
void ESDConnectionManager::Run()
{
try
{
// Create the endpoint
mWebsocket.clear_access_channels(websocketpp::log::alevel::all);
mWebsocket.clear_error_channels(websocketpp::log::elevel::all);
// Initialize ASIO
mWebsocket.init_asio();
// Register our message handler
mWebsocket.set_open_handler(websocketpp::lib::bind(&ESDConnectionManager::OnOpen, this, &mWebsocket, websocketpp::lib::placeholders::_1));
mWebsocket.set_fail_handler(websocketpp::lib::bind(&ESDConnectionManager::OnFail, this, &mWebsocket, websocketpp::lib::placeholders::_1));
mWebsocket.set_close_handler(websocketpp::lib::bind(&ESDConnectionManager::OnClose, this, &mWebsocket, websocketpp::lib::placeholders::_1));
mWebsocket.set_message_handler(websocketpp::lib::bind(&ESDConnectionManager::OnMessage, this, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2));
websocketpp::lib::error_code ec;
std::string uri = "ws://127.0.0.1:" + std::to_string(mPort);
WebsocketClient::connection_ptr connection = mWebsocket.get_connection(uri, ec);
if (ec)
{
DebugPrint("Connect initialization error: %s\n", ec.message().c_str());
return;
}
mConnectionHandle = connection->get_handle();
// Note that connect here only requests a connection. No network messages are
// exchanged until the event loop starts running in the next line.
mWebsocket.connect(connection);
// Start the ASIO io_service run loop
// this will cause a single connection to be made to the server. mWebsocket.run()
// will exit when this connection is closed.
mWebsocket.run();
}
catch (websocketpp::exception const & e)
{
// Prevent an unused variable warning in release builds
(void)e;
DebugPrint("Websocket threw an exception: %s\n", e.what());
}
}
This appears to be using some library called boost.asio? The closest thing I can find in C# is the MessageWebSocket from Windows.Networking.Sockets (documentation here) but this appears to be only for Windows RT?
How do I create something analogous to this in a .NET console app? I have found references to System.Net.WebSockets.ClientWebSocket (documentation here), which appears to be the class I need, but I am not sure.
I have found a few samples (such as this one, and this one - both of which use yet another socket class, Socket) that show how to use Sockets in general, but they do not seem event-driven. They seem to send, and then immediately receive data. I want a web socket that calls local methods (akin to event handlers) when events/data are received by the socket. I believe this is what is going on in the sample C++ code above (specifically Open, Fail, Close, and Message). My understanding is that I need to do some work ("register" with the Stream Deck) on the web socket "Open" event, and then handle the web socket "Message" event and parse out what event the Stream Deck is reporting happened.
If you scroll down some lines in your example https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket?view=net-7.0 you will find a example called: Asyncronous Mode that handles sending and receiving separately.
Send part
int bytesSent = 0;
while (bytesSent < requestBytes.Length)
{
bytesSent += await socket.SendAsync(requestBytes.AsMemory(bytesSent), SocketFlags.None);
}
If you do not want the program to lock up, the easiest way would be to start a thread for listening maybe?

SerialPort.ReadTo getting data when doing Step Over, but not on normal execution

I'm building a WPF app that has to communicate through a Serial Port. When I send some data to the serial port it is supposed to reply with some data. For example, I send a PIG\r\n and it reply with ACK\r\n. During a normal execution of the code, I send a command to get me some data from a third device connect to the second (which is attached to my serial port) I don't get any reply, only a timeout exception. However, when I try to debug the code (using step over) it works as expected.
I have try to do Step over short than the Timeout (30s) and still gets the problem.
I have create a console application to test my code and it works fine on it. So, I'm assume there are some problems on WPF, But I don't know where to look.
My Read function
public ComandoFactory Ler()
{
try
{
string Mensagem = sp.ReadTo("\r\n");
var comando = new ComandoFactory(Mensagem.Substring(0,3), Mensagem.Substring(3));
return comando;
}
catch (TimeoutException e)
{
return new ComandoFactory("ERR", "TIMEOUT");
}
catch(ArgumentOutOfRangeException e)
{
return new ComandoFactory("ERR", "ARGUMENT");
}
}
ReadTo should return something, instead of giving a Timeout.
Any help is welcome. Thanks
I fixed this by creating a small wait between the Write and read operation. 100 ms did the trick and the code is working now. However, I know this is not the best solution. #Baddack idea of using DataReceived is probably better and I'll try when I can.

Connecting to Multiple TCP Servers From Client C#

Making the properties TcpClient and IPEndPoint appear to have fixed my issue! If anyone could explain why this is the case I would appreciate it. I do usually declare my class objects static but I don't entirely understand why it works this way.
I'd like to start by saying the usual, I've googled and googled but haven't found anything answering my question so please point me if there is already an answer to this question.
I have written successfully a TCP server and client in C#, however I would like my client to be able to connect to multiple servers. To be clear this is not a server with multiple clients connected to it, I had no issues configuring that.
Here is a little picture explaining what I mean:
Pretty, I know. But in all seriousness I can't get this to work. I met with the error: A connect request was made on an already connected socket
I have a class called client, with a TcpClient and an IPEndPoint:
public Client(IPEndPoint ip)
{
client = new TcpClient();
this.ip = ip;
}
This class has methods connect, send, receive etc. The issue comes when I do something like this:
Client host = new Client(hosts.ElementAt(0));
IPEndPoint ipe = hosts.ElementAt(0);
EDIT: This contructor occurs in a different method than the method the "host" constructor does
Client client = new Client(ipe);
client.ConnectAsync();
host.ConnectAsync();
Now originally I tried to use the new async methods and the await feature, it worked fine when it was only one host but on the second it began to error. I thought perhaps it was becuase I was using the same method and it was attempting to connect before the first await had completed, it would try to connect again on the first IP, no idea if that makes any sense but basically I thought, well I will just create a new thread for each connect attempt like so:
public void ConnectAsync()
{
ThreadPool.QueueUserWorkItem(delegate { ConnectAsyncMethod(); });
}
private void ConnectAsyncMethod()
{
Thread connectThread = new Thread(() =>
{
try
{
client.Connect(ip.Address, ip.Port);
this.clientStream = client.GetStream();
ReceiveAsync();
}
catch (SocketException se)
{
}
catch (NotSupportedException ns)
{
}
catch (Exception e)
{
}
});
connectThread.Start();
}
Even though the connect is run on a new thread, I still get the same error, but why?
Could anyone point me towards a solution and hopefully explain where the flaws in my thinking lie? I am now thinking perhaps it is something in the way sockets are handled but I'm really not sure.
I appreciate any help, thank you everyone.
You will need multiple Client objects to establish multiple connections to different addresses (or the same in fact). For example, you could have a Client ClientA connect to Server A and have a Client ClientB connect to Server B. You cannot have the same Client object connect two times to diffrent or the same address.
This is strange.Maybe you would check whether the 2nd client port conflicts with the first client which will result in the error.
Here I found the official manual of this(10056):
http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa924071(v=vs.85).aspx

TCPClient & Sockets failing to connect to the Server

I have a very strange problem with my connection to a server on a TCPListener/TCPClient basis. At some point during testing I am unable to connect to my server-application anymore, every try it times out. Netstats on both sides show, that my application listens on the right port, and the client is trying to connect to the right ip and port, but it does not advance further than "SYN_SENT". The server just displays "LISTENING" all the time. All I can do is restart my PC, which temporarily fixes this problem. But after some connections, it starts all over again.
Up to now I tested TCPClient and Sockets class to connect to the server but both show this behaviour, what is not surprising, as TCPClient is a wrapper around the Sockets Class afaik.
Firewall is checked on both sides, things like Remote Desktop work perfectly fine, and is not blocking the Connection of my Application. There are no connections left to close or something, already cheked everything I know (maybe not that much ;) )
So whats the problem?
Edit:
A Method that needs to connect to my Server:
public int GetSomeDataFromServer(string blargh)
{
int ret;
try
{
using(ConnectionTCPStream ctp = new ConnectionTCPStream())
{
if(ctp.EstSecConnWithServ())
{
ret = CKSHandler(ctp, blargh);
}
else
{ ret = (int)ErrFlags.ServerDeniedConnection; }
}
return ret;
}
catch(Exception)
{
InternalError = ErrFlags.ServerUnreachable;
return (int)ErrFlags.ServerUnreachable;
}
}
The Constructor of my Class that is dealing with the Connections:
public ConnectionTCPStream()
{
Client = new TcpClient("VeryImportantAdress", 49778); //it fails right here!
rsaCrypt = new RSACH() { RSAForeignPubKey = "An 8192-Bit long RSA Public key." };
AESPASS = AESThenHMAC.CreatePassword(200);
}
Sounds like you are using up all your connections or some other resource.
What do you see when you do a netstat -an ? Do you see a bunch of open ports?
There an Article Here that could possibly help you here
Some other resource may be killing you, might be worth having an SA fire up a resource monitor to check the health of the host when you run into this situation.
If there's no errors being thrown, it makes your life that much harder. The problem typically happens when you don't cleanly clean up your socket disconnects.
The answer is the firewall which changed its mind every now and then. I couldn't test that before because i had no access to it. Now i have changed settings while i had this blockade and it worked fine again. So the answer is: Always have access to the firewall and don't forget to check it.

Multithreading using AsyncCallback and GUI controls

Multithread programming is a new concept for me. I’ve done a bunch of reading and even with many examples, I just can’t seem to figure it out. I'm new to C# and programming.
I have a winform project with lots of custom controls I’ve imported and will utilize many tcpclients. I’m trying to get each control to be hosted on it’s own separate thread. Right now, I’m trying to get 1 control to behave appropriately with it’s own thread.
I'll show you what I have and then follow up with some questions regarding guidance.
string asyncServerHolder; // gets the server name from a text_changed event
int asyncPortHolder; // gets the port # from a text_changed event
TcpClient wifiClient = new TcpClient();
private void btnStart_Click(object sender, EventArgs e)
{
... // variable initialization, etc.
... // XML setup, http POST setup.
send(postString + XMLString); // Content to send.
}
private void send(string msg)
{
AsyncCallback callBack = new AsyncCallback(ContentDownload);
wifiClient.BeginConnect(asyncServerHolder, asyncPortHolder, callBack, wifiClient);
wifiClient.Client.Send(System.Text.Encoding.ASCII.GetBytes(msg));
}
private void ContentDownload(IAsyncResult result)
{
if (wifiClient.Connected)
{
string response4 = "Connected!!"; //debug msg
byte[] buff = new byte[1024];
int i = wifiClient.Client.Receive(buff);
do
{
response1 = System.Text.Encoding.UTF8.GetString(buff, 0, i);
} while (response1.Length == 0);
response2 = response1.Substring(9, 3); // pick out status code to be displayed after
wifiClient.Client.Dispose();
wifiClient.Close();
}
}
If you're knowledgeable about this, I bet you see lots of problems above. As it stands right now, I always get an exception one my first iteration of running this sequence:
"A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied"
Why is this? I have confirmed that my asyncServerHolder and my asyncPortHolder are correct. My second iteration of attempting allowed me to see response4 = "Connected!!" but I get a null response on response1.
Eventually I'd like to substitute in my user controls which I have in a List. I'd just like to gracefully connect, send my msg, receive my response and then allow my form to notify me from that particular control which plays host to that tcp client. My next step would be link up many controls.
Some questions:
1) Do I need more TCP clients? Should they be in a list and be the # of controls I have enabled at that time of btnStart_Click?
2) My controls are on my GUI, does that mean I need to invoke if I'm interacting with them?
3) I see many examples using static methods with this context. Why is this?
Thanks in advance. All criticism is welcome, feel free to be harsh!
BeginConnect returns immediately. Probably, no connection has been established yet when Send runs. Make sure that you use the connection only after having connected.
if (wifiClient.Connected) and what if !Connected? You just do nothing. That's not a valid error recovery strategy. Remove this if entirely.
In your read loop you destroy the previously read contents on each iteration. In fact, you can't split up an UTF8 encoded string at all and decode the parts separately. Read all bytes into some buffer and only when you have received everything, decode the bytes to a string.
wifiClient.Client.Dispose();
wifiClient.Close();
Superstitious dispose pattern. wifiClient.Dispose(); is the canonical way to release everything.
I didn't quite understand what "controls" you are talking about. A socket is not a control. UI controls are single-threaded. Only access them on the UI thread.
Do I need more TCP clients?
You need one for each connection.
Probably, you should use await for all blocking operations. There are wrapper libraries that make the socket APIs usable with await.

Categories