1
0
mirror of https://github.com/lidgren/lidgren-network-gen3.git synced 2026-05-06 02:11:06 +09:00

Added code to rebind socket after a NetConnected socket error; thanks Rhee

This commit is contained in:
lidgren
2014-10-08 12:08:43 +00:00
parent f476f523ac
commit e206ba210e
5 changed files with 78 additions and 44 deletions

View File

@@ -1,4 +1,4 @@
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE
#define IS_MAC_AVAILABLE
#endif
@@ -24,6 +24,7 @@ namespace Lidgren.Network
private object m_initializeLock = new object();
private uint m_frameCounter;
private double m_lastHeartbeat;
private double m_lastSocketBind = float.MinValue;
private NetUPnP m_upnp;
internal readonly NetPeerConfiguration m_configuration;
@@ -102,6 +103,46 @@ namespace Lidgren.Network
}
}
private void BindSocket(bool reBind)
{
double now = NetTime.Now;
if (now - m_lastSocketBind < 1.0)
{
LogDebug("Suppressed socket rebind; last bound " + (now - m_lastSocketBind) + " seconds ago");
return; // only allow rebind once every second
}
m_lastSocketBind = now;
if (m_socket == null)
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
if (reBind)
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize;
m_socket.SendBufferSize = m_configuration.SendBufferSize;
m_socket.Blocking = false;
var ep = (EndPoint)new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port);
m_socket.Bind(ep);
try
{
const uint IOC_IN = 0x80000000;
const uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
}
catch
{
// ignore; SIO_UDP_CONNRESET not supported on this platform
}
IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint;
LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound);
m_listenPort = boundEp.Port;
}
private void InitializeNetwork()
{
lock (m_initializeLock)
@@ -121,32 +162,7 @@ namespace Lidgren.Network
m_handshakes.Clear();
// bind to socket
IPEndPoint iep = null;
iep = new IPEndPoint(m_configuration.LocalAddress, m_configuration.Port);
EndPoint ep = (EndPoint)iep;
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize;
m_socket.SendBufferSize = m_configuration.SendBufferSize;
m_socket.Blocking = false;
m_socket.Bind(ep);
try
{
const uint IOC_IN = 0x80000000;
const uint IOC_VENDOR = 0x18000000;
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
m_socket.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
}
catch
{
// ignore; SIO_UDP_CONNRESET not supported on this platform
}
IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint;
LogDebug("Socket bound to " + boundEp + ": " + m_socket.IsBound);
m_listenPort = boundEp.Port;
BindSocket(false);
m_receiveBuffer = new byte[m_configuration.ReceiveBufferSize];
m_sendBuffer = new byte[m_configuration.SendBufferSize];
@@ -175,6 +191,7 @@ namespace Lidgren.Network
// not supported; lets just keep the random bytes set above
}
#endif
IPEndPoint boundEp = m_socket.LocalEndPoint as IPEndPoint;
byte[] epBytes = BitConverter.GetBytes(boundEp.GetHashCode());
byte[] combined = new byte[epBytes.Length + macBytes.Length];
Array.Copy(epBytes, 0, combined, 0, epBytes.Length);
@@ -255,9 +272,20 @@ namespace Lidgren.Network
{
m_socket.Shutdown(SocketShutdown.Receive);
}
catch { }
catch(Exception ex)
{
LogDebug("Socket.Shutdown exception: " + ex.ToString());
}
try
{
m_socket.Close(2); // 2 seconds timeout
}
catch (Exception ex)
{
LogDebug("Socket.Close exception: " + ex.ToString());
}
}
}
finally
{
@@ -270,6 +298,7 @@ namespace Lidgren.Network
m_messageReceivedEvent.Set();
}
m_lastSocketBind = float.MinValue;
m_receiveBuffer = null;
m_sendBuffer = null;
m_unsentUnconnectedMessages.Clear();
@@ -393,17 +422,24 @@ namespace Lidgren.Network
}
catch (SocketException sx)
{
if (sx.SocketErrorCode == SocketError.ConnectionReset)
switch (sx.SocketErrorCode)
{
case SocketError.ConnectionReset:
// connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
// we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
// So, what to do?
LogWarning("ConnectionReset");
return;
}
LogWarning(sx.ToString());
case SocketError.NotConnected:
// socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
BindSocket(true);
return;
default:
LogWarning("Socket exception: " + sx.ToString());
return;
}
}
if (bytesReceived < NetConstants.HeaderByteSize)

View File

@@ -28,7 +28,7 @@ namespace Lidgren.Network
[CLSCompliant(false)]
public static ulong GetUInt64()
{
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE
ulong seed = (ulong)System.Diagnostics.Stopwatch.GetTimestamp();
seed ^= (ulong)Environment.WorkingSet;
ulong s2 = (ulong)Interlocked.Increment(ref m_seedIncrement);

View File

@@ -16,7 +16,7 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRA
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER
#if !__ANDROID__ && !IOS && !UNITY_WEBPLAYER && !UNITY_ANDROID && !UNITY_IPHONE
#define IS_FULL_NET_AVAILABLE
#endif
@@ -599,7 +599,7 @@ namespace Lidgren.Network
/// </summary>
public static byte[] CreateSHA1Hash(string key)
{
using (var sha = SHA1.Create())
using (var sha = new SHA1CryptoServiceProvider())
return sha.ComputeHash(Encoding.UTF8.GetBytes(key));
}
@@ -608,7 +608,7 @@ namespace Lidgren.Network
/// </summary>
public static byte[] CreateSHA1Hash(byte[] data)
{
using (var sha = SHA1.Create())
using (var sha = new SHA1CryptoServiceProvider())
return sha.ComputeHash(data);
}
}

View File

@@ -93,7 +93,6 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>

View File

@@ -95,7 +95,6 @@
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>