Handle failure cases of Socket.Send. Fixes #3455.

This commit is contained in:
Paul Chote
2013-06-27 17:32:12 +12:00
parent 39e97ee767
commit 8856a1444c

View File

@@ -200,13 +200,10 @@ namespace OpenRA.Server
newConn.socket.Blocking = false; newConn.socket.Blocking = false;
newConn.socket.NoDelay = true; newConn.socket.NoDelay = true;
Log.Write("server", "Socket.ReceiveBufferSize: {0}.".F(newConn.socket.ReceiveBufferSize));
Log.Write("server", "Socket.SendBufferSize: {0}.".F(newConn.socket.SendBufferSize));
// assign the player number. // assign the player number.
newConn.PlayerIndex = ChooseFreePlayerIndex(); newConn.PlayerIndex = ChooseFreePlayerIndex();
newConn.socket.Send(BitConverter.GetBytes(ProtocolVersion.Version)); SendData(newConn.socket, BitConverter.GetBytes(ProtocolVersion.Version));
newConn.socket.Send(BitConverter.GetBytes(newConn.PlayerIndex)); SendData(newConn.socket, BitConverter.GetBytes(newConn.PlayerIndex));
preConns.Add(newConn); preConns.Add(newConn);
// Dispatch a handshake order // Dispatch a handshake order
@@ -382,12 +379,10 @@ namespace OpenRA.Server
{ {
try try
{ {
var ms = new MemoryStream(); SendData(c.socket, BitConverter.GetBytes(data.Length + 4));
ms.Write(BitConverter.GetBytes(data.Length + 4)); SendData(c.socket, BitConverter.GetBytes(client));
ms.Write(BitConverter.GetBytes(client)); SendData(c.socket, BitConverter.GetBytes(frame));
ms.Write(BitConverter.GetBytes(frame)); SendData(c.socket, data);
ms.Write(data);
c.socket.Send(ms.ToArray());
} }
catch (Exception e) catch (Exception e)
{ {
@@ -595,5 +590,29 @@ namespace OpenRA.Server
gameTimeout.Enabled = true; gameTimeout.Enabled = true;
} }
} }
void SendData(Socket s, byte[] data)
{
var start = 0;
var length = data.Length;
SocketError error;
// Non-blocking sends are free to send only part of the data
while (start < length)
{
var sent = s.Send(data, start, length - start, SocketFlags.None, out error);
if (error == SocketError.WouldBlock)
{
Log.Write("server", "Non-blocking send of {0} bytes failed. Falling back to blocking send.", length - start);
s.Blocking = true;
sent = s.Send(data, start, length - start, SocketFlags.None);
s.Blocking = false;
}
else if (error != SocketError.Success)
throw new SocketException((int)error);
start += sent;
}
}
} }
} }