|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
UDP Comms and Connection Reset ProblemSystem.Net.Sockets. The Socket.EndReceiveFrom() often throws a SocketException (ErrorCode: 10054, WSAECONNRESET, "An existing connection was forcibly closed by the remote host"). This seems to be a common problem affecting a lot of people and it appears that this happens due to 'ICMP Port unreachable' responses to the UDP messages already sent out. KB263823 (http://support.microsoft.com/kb/263823/en-us) explains the problem. Looking at the above KB I expect to get SocketExceptions with WSAECONNRESET during Socket.EndReceiveFrom(). And they do happen often. But sometimes I also get same exception during Socket.BeginReceiveFrom(). Why? What is the best way to fix this problem? Should we be using Socket.IOControl() to set SIO_UDP_CONNRESET to false? (Our application runs on Windows Server 2003) Or should we be catching SocketExceptions and ignoring the WSAECONNRESET errors? Jonas Hei wrote:
Hi Jonas, > Looking at the above KB I expect to get SocketExceptions with I had the same problem just a few weeks ago. And I hate it for throwing > WSAECONNRESET during Socket.EndReceiveFrom(). And they do happen often. > > But sometimes I also get same exception during > Socket.BeginReceiveFrom(). Why? in BeginReceiveFrom!! My whole code was full of try/catches because of that. > What is the best way to fix this problem? Since I found out about the IOControl call with SIO_UDP_CONNRESET the problem is gone (no more silly exceptions that I don't care about with UDP!). I've successfully used that on W2K and XP so far. Simply disabling that behaviour should definitelly be cheaper than catching exceptions -- catching wastes lots of cpu cycles. hth, Max Markus Stoeger wrote:
> Since I found out about the IOControl call with SIO_UDP_CONNRESET the Max, thanks a lot for the solution.> problem is gone (no more silly exceptions that I don't care about with > UDP!). I've successfully used that on W2K and XP so far. > By the way how did you set SIO_UDP_CONNRESET to FALSE? I have tried doing as per Zupancic's suggestion (http://blog.devstone.com/aaron/archive/2005/02/20.aspx): // 0x9800000C == 2440136844 (uint) == -174483042 (int) == 0x9800000C const int SIO_UDP_CONNRESET = -174483042; byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0 _socket.IOControl(SIO_UDP_CONNRESET, inValue, outValue); But it does not work for me - it throws a SocketException (An invalid argument was supplied). The code illustrated in http://thedotnet.com/nntp/8375/showpost.aspx does not work for me either. By the way I am currently on .NET1.1/VS2003. Even if I had been on .NET2.0 I guess the new method Socket.IOControl(IOControlCode, Byte[], Byte[]) wouldn't have helped me...I couldn't find the equivalent for SIO_UDP_CONNRESET in IOControlCode enum (http://msdn2.microsoft.com/en-us/library/system.net.sockets.iocontrolcode.aspx) Jonas Hei wrote:
> I have tried doing as per Zupancic's suggestion Zupancic was just telling us that it is kind of lame to copy and paste > (http://blog.devstone.com/aaron/archive/2005/02/20.aspx): > // 0x9800000C == 2440136844 (uint) == -174483042 (int) == 0x9800000C > const int SIO_UDP_CONNRESET = -174483042; > byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false > byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0 > _socket.IOControl(SIO_UDP_CONNRESET, inValue, outValue); > > But it does not work for me - it throws a SocketException (An invalid > argument was supplied). > code snippets from anywhere without giving them a serious thought first. So after being lame for a few hours (give or take a few more hours), I finally gave some thought to it and luckily managed to solve the problem: instead of // 0x9800000C == 2440136844 (uint) == -174483042 (int) == 0x9800000C we need // 0x9800000C == 2550136844 (uint) == -1744830452 (int) == 0x9800000C so this snippet seems to work: const int SIO_UDP_CONNRESET = -1744830452; byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0 _socket.IOControl(SIO_UDP_CONNRESET, inValue, outValue); Jonas Hei wrote:
Show quote > Jonas Hei wrote: I used the following code... looks clean to me. I don't think it's > Zupancic was just telling us that it is kind of lame to copy and paste > code snippets from anywhere without giving them a serious thought first. > > So after being lame for a few hours (give or take a few more hours), I > finally gave some thought to it and luckily managed to solve the problem: > instead of > // 0x9800000C == 2440136844 (uint) == -174483042 (int) == 0x9800000C > we need > // 0x9800000C == 2550136844 (uint) == -1744830452 (int) == 0x9800000C > > so this snippet seems to work: > > const int SIO_UDP_CONNRESET = -1744830452; > byte[] inValue = new byte[] { 0, 0, 0, 0 }; // == false > byte[] outValue = new byte[] { 0, 0, 0, 0 }; // initialize to 0 > _socket.IOControl(SIO_UDP_CONNRESET, inValue, outValue); necessary to pass arrays of 4 bytes. 1 byte is enough. And the second array can be null because we don't need the return values: uint IOC_IN = 0x80000000; uint IOC_VENDOR = 0x18000000; uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12; s.IOControl((int)SIO_UDP_CONNRESET, new byte[] {Convert.ToByte(false)}, null); Max |
|||||||||||||||||||||||