2013-05-02 3 views
2

Мне было интересно, есть ли способ избегать, получая исключение SocketException, когда я не могу подключиться, а не ловить SocketException, используя try/catch.C# - Избегайте получения SocketException

У меня есть этот код, который проверяет, если сервер доступен из не:

public bool CheckServerStatus(string IP, int Port) 
    { 
     try 
     { 
      IPAddress[] IPs = Dns.GetHostAddresses(IP); 

      using (Socket s = new Socket(AddressFamily.InterNetwork, 
       SocketType.Stream, 
       ProtocolType.Tcp)) 
      s.Connect(IPs[0], Port); 

      return true; 
     } 
     catch (SocketException) 
     { 
      return false; 
     } 
    } 

Спасибо заранее.

+1

Почему вы хотите сделать это? Разве вы не можете просто ничего не делать в выводе? – Meoiswa

+3

Согласно msdn: SocketException генерируется классами Socket и Dns при возникновении ошибки в сети. Таким образом, это означает, что вы не можете полностью избежать этого. –

ответ

4

Вы можете подкласс Socket и предоставить конкретную реализацию:

public class MySocket : Socket{ 
    //... 
    public boolean TryConnect(...){ 
    } 
} 

Можно также вместо булева, возвращать Result объект, сохранить исключение для обработки ошибок:

public class Result { 
    public Exception Error { get; set; } 
    public boolean Success { get{ return Error != null; } } 
} 
+1

Вы можете сделать это, но это только перемещает «проблему» в другое место. В этом методе 'TryConnect' вы все равно получите' SocketException' в той же ситуации. Вы просто справляетесь с этим в другой точке. – pyrocumulus

+1

Правда, но если этот класс предназначен для повторного использования, вы должны обрабатывать его в _only__one_ point. –

+0

Это преимущество да, хотя это не то, о чем он просит, поскольку он специально просит избежать самого исключения. Но, в зависимости от того, сколько раз он создает сокеты, это может быть более чистый способ сделать это действительно :) – pyrocumulus

3

Получения SocketException не проблема; это то, для чего следует использовать исключение. В зависимости от типа исключения, которое вы получаете, вы можете обрабатывать их разными способами. Было бы неплохо, если бы вы только что поймали Exception, а не более конкретно SocketException.

Почему вы хотите избежать этого? Как говорится в комментариях, в какой-то момент код будет сбой, если другой конец соединения недоступен. Просто убедитесь, что вы поймаете эту неудачу в соответствующем месте, как будто вы сейчас делаете.

+0

Не обязательно. Ошибка может быть допустимым результатом, а не «исключением». Ошибки могут отображаться в пользовательском интерфейсе или сохраняться. Использование исключений для управления потоком - плохая идея, и я ненавижу, как у BCL, похоже, есть что-то для этого во многих API. Намного лучше вернуть результат и позволить пользователю решить, как с ним справиться. – hcoverlambda

+0

BTW, просто протестировал исключение против нет, 25x perf hit.В некоторых сценариях может быть хорошо, не так хорошо в других. – hcoverlambda

1

Возможно, вы можете решить проблему в первую очередь, используя Ahmed approach, но это просто переводит проблему на рычаг глубже.

Основная причина, по которой такой метод испытаний не существует, - это возможность состояния гонки. Представьте, что вы проверите, возможен ли такой сокет, и прежде чем вы сможете попытаться установить этот сокет в следующей строке, произойдет переход контекста (к другому потоку или приложению), который просто назначает этот сокет для себя. Теперь вы все еще получаете исключение, и вам нужно проверить его (используя подход try-catch).

Таким образом, этот тест просто не приносит пользы вашему коду, потому что вы все еще должны быть готовы к сбою этого метода. И в этом причина этого теста не существует.

1

мне удалось добиться этого с помощью BeginConnect следующего

int connectTimeoutMS = 1000; 
IPEndPoint endPoint = GetEndPoint(); 
var evt = new AutoResetEvent(false); 
_socket.BeginConnect(endPoint, (AsyncCallback)delegate { evt.Set(); }, null); 
evt.WaitOne(connectTimeoutMS); 
Смежные вопросы