-1

The code below will fail because Bind() is called on a socket that has not been "prepared", even though there is code to prepare the socket. The code that prepares the socket is out of scope (another Try block).

        // prepare socket
        try
        {
            socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }
        catch (Exception e)
        {
            log.write("socket preparation failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

        // bind
        try
        {
            socket.Bind(endPoint);
        }   
        catch (Exception e)
        {
            log.write("Bind() failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }

        // enable listening
        try
        {
            socket.Listen(1000);
        }
        catch (Exception e)
        {
            log.write("Listen() failed");
        }
        finally
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
paperduck
  • 1,175
  • 1
  • 16
  • 26

3 Answers3

2

Here's one way to write it. The finally is part of an outer scope, while all your catches are in inner scope. I'm throwing after each catch, but you can handle it differently.

Note that each finally clause is executed as soon as it's corresponding try clause falls out of scope, not when the method exists.

    Socket socket;

    try
    {
        // prepare socket
        try
        {
            socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        }
        catch
        {
            log.write("socket preparation failed");
            throw;
        }

        // bind
        try
        {
            socket.Bind(endPoint);
        }   
        catch
        {
            log.write("Bind() failed");
            throw;
        }

        // enable listening
        try
        {
            socket.Listen(1000);
        }
        catch
        {
            log.write("Listen() failed");
            throw;
        }
    }
    finally
    {
        if (socket != null)
        {
            socket.Shutdown(SocketShutdown.Both);
            socket.Close();
        }
    }
Nathan A
  • 11,059
  • 4
  • 47
  • 63
0

If the exceptions are always being treated the same way, why don't you try this way...

string message = string.Empty;

try
{
    message = "socket preparation failed";
    socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

    message = "Bind() failed";
    socket.Bind(endPoint);

    message = "Listen() failed";
    socket.Listen(1000);

    message = string.Empty;
}
catch
{
    log.write(message);
}
finally
{
    if (socket != null)
    {
        socket.Shutdown(SocketShutdown.Both);
        socket.Close();
    }
}
Carlos Oliveira
  • 477
  • 6
  • 11
0

In cases like this, I like to use custom wrapper classes, I find them to be a bit neater and have a bit more ability to customize to your needs (especially when it comes to throwing errors in a neater fashion)

So you could write a class that implements Socket, we'll call it CustomSocket

public class CustomSocket : Socket {

    private EndPoint endPoint;

    public CustomSocket(EndPoint endPoint, SocketType socketType, ProtocolType protocolType)
        : base(endPoint.AddressFamily, socketType, protocolType) {
            this.endPoint = endPoint;
    }

    public virtual void Bind() {
        try {
            base.Bind(endPoint);
        } catch {
            // do logging here
            throw new Exception("Bind() failed");
        }
    }

    public virtual void Listen(int backlog) {
        try {
            base.Listen(backlog);
        } catch {
            // do logging here
            throw new Exception("Listen() failed");
        }
    }

    public void Dispose() {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
    }
}

And then you could implement it like so:

        using (CustomSocket socket = new CustomSocket(new IPEndPoint(new IPAddress(new byte[1]), 5000), SocketType.Stream, ProtocolType.Tcp)) {
            try {
                socket.Bind();
                socket.Listen(1000);
            } catch (Exception ex) {
                // do stuff with ex here
            }
        }

Also, implementing the using method of doing this will make it so you don't have to manually call Close() and/or Shutdown(). (using automatically calls Dispose() when it reaches the end, and Dispose() is the same thing as Close(). When Close() is called, if you haven't already explicitly initiated a Shutdown() it will initiate it for you)

Ben Black
  • 3,751
  • 2
  • 25
  • 43