c# - Canceling an asynchronous socket operation -
i have c# .net 3.5 application sends multicast "hello" packet whomever may subscribed particular multicast group , listens responses. so, every x seconds, may send "hello" packet , make note of responds.
it intended used this:
multicasthello hello_ = new multicasthello(); // alert our ui of responses 'hello' hello_.receivedhelloresponse += onhelloresponse; // timer function triggered every x seconds private void ontimer(object sender, eventargs e) { // stop listening responses last 'hello' hello_.cancelhello(); // send new 'hello' , start listening responses hello_.sendhello("224.0.100.1"); }
unfortunately, i'm having issues canceling asynchronous read. private void onreceive(iasyncresult ar)
function throw system.argumentexception
says "the iasyncresult object not returned corresponding asynchronous method on class."
how can reliably cancel asynchronous socket operation. or, there better way of doing this?
my implementation below.
thanks, paulh
public class helloresponseeventargs : eventargs { /*...*/ } public class multicasthello : idisposable { public event eventhandler<helloresponseeventargs> receivedhelloresponse; private socket socket_; private byte[] received_ = new byte[helloresponse.size]; private endpoint responder_ = new ipendpoint(ipaddress.any, 0); protected virtual void onreceivedhelloresponse(helloresponseeventargs e) { eventhandler<helloresponseeventargs> evt = receivedhelloresponse; if (null != evt) evt(this, e); } private void onreceive(iasyncresult ar) { ipendpoint ipendpoint = new ipendpoint(ipaddress.any, 0); endpoint endpoint = ipendpoint endpoint; try { socket_.endreceivefrom(ar, ref endpoint); } catch (system.objectdisposedexception) { // read canceled. expected. return; } // decode response , set event ipendpoint remote = endpoint ipendpoint; helloresponse response = new helloresponse(deserialize<hellopacket>(received_)); onreceivedhelloresponse(new helloresponseeventargs(remote.address.tostring(), response)); // keep receiving responses until canceled socket_.beginreceivefrom(received_, 0, received_.length, socketflags.none, ref endpoint, new asynccallback(onreceive), null); } // stop listening responses hello frame public void cancelhello() { if (socket_ != null) socket_.close(); } // send initial 'hello' multicast address. start listening responses public void sendhello(string address) { socket_ = new socket(addressfamily.internetwork, sockettype.dgram, protocoltype.udp); socket_.multicastloopback = false; socket_.ttl = 255; helloresponse send = new helloresponse(); byte[] data = serialize(send.packet); endpoint remote = new ipendpoint(ipaddress.parse(address), 7); socket_.sendto(data, remote); socket_.beginreceivefrom(received_, 0, received_.length, socketflags.none, ref responder_, new asynccallback(onreceive), null); } #region idisposable members /* close socket on dispose*/ #endregion }
send socket state arg in beginreceive. i.e.
socket_.beginreceivefrom( received_, 0, received_.length, socketflags.none, ref endpoint, new asynccallback(onreceive), socket_);
then in onreceive use instead of class variable socket. i.e.
socket socket = (socket)ar.asyncstate; socket.endreceivefrom(ar, ref endpoint);
this ensures endreceivefrom call happening on same socket beginreceive called on. paulh mentions catch objectdisposedexception in onreceive signal close() called on socket.
-oli
Comments
Post a Comment