Без действующего примера это трудно понять.Если это близко к тому, что вы на самом деле делаете, я подозреваю, что пара вещей не так.Объект Socket, по-видимому, блокируется по умолчанию, но что-то генерирует ваше исключение, и это может быть не то, что вы думаете.Первое, что нужно сделать, это только перехватить SocketException, а затем только повторную попытку, когда исключение представляет что-то, что может указывать на то, что повторная попытка будет работать.Задержка, потому что если она не сработала 1 мс назад, то, вероятно, не сработает сейчас.Вставьте счетчик здравомыслия, чтобы он прекратил попытки после стольких попыток.Проверьте ваш протокол, чтобы убедиться, что вы отправляете серверу то, что он ожидает.Прежде всего, закройте ваши сокеты.
Я подозреваю, что вы видите набор соединений сокетов, вызванных исключением (которое может или не может быть связано с сокетами).Так как вы никогда не закрываете их, они просто накапливаются.Я подозреваю, что в конечном итоге GC может запустить и запустить финализаторы на объектах, которые затем потеряют свои соединения.Скорее всего, сервер потеряет связь.В любом случае, если вы явно не закрываете сокет, он будет зависать до тех пор, пока не произойдет тайм-аут.
Вот рабочий пример, который демонстрирует то, о чем я думаю, вы спрашиваете.Опять же, вам нужно решить, при каких условиях вы должны повторить попытку, потому что повторная попытка, если что-то пойдет не так, не годитсяЭто может привести к тому, что ваша программа будет постоянно чередовать потоки и, возможно, даже соединения.
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using Microsoft.Extensions.Logging;
namespace socketTst {
class Program {
static ILoggerFactory loggerFactory = new LoggerFactory().AddConsole().AddDebug();
static ILogger _logger;
static AutoResetEvent finish = new AutoResetEvent(false);
static String Hostname = "www.google.com";
static int Port = 80;
static int RetryCount = 0;
static void ConnectCallback(IAsyncResult ar) {
_logger.LogInformation($"## ConnectCallback entered");
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
try {
// Complete the connection.
client.EndConnect(ar);
var s = new byte[] { 1 };
client.Send(s);
var buf = new byte[1024];
var cnt = client.Receive(buf);
_logger.LogInformation($"## Connection to server successful at {client.RemoteEndPoint}");
if (cnt > 0) {
var returned = Encoding.UTF8.GetString(buf, 0, cnt);
_logger.LogInformation($"## Data returned: {returned}");
}
else {
_logger.LogInformation($"## No data returned");
}
finish.Set(); // signal end of program
}
catch (SocketException sockExcep) {
_logger.LogInformation($"## Exception: {sockExcep.Message}");
_logger.LogInformation("## Connection to server failed. Retrying...");
// This is a bad idea. You don't know what is wrong so retrying might not be useful.
// What if this is an unknown host or some other error that isn't likely to be
// resolved by a retry ???
RetryCount++;
if (RetryCount > 10) {
_logger.LogInformation("## Not able to reach host after 10 tries");
finish.Set(); // signal end of program
return; // give up
}
Thread.Sleep(797); // wait a bit
var dest = new DnsEndPoint(Hostname, Port);
client.BeginConnect(dest, new AsyncCallback(ConnectCallback), client);
}
catch (Exception ex) {
_logger.LogInformation($"## Exception: {ex.Message}");
}
_logger.LogInformation($"## ConnectCallback exited");
}
static void Main(string[] args) {
_logger = loggerFactory.CreateLogger<Program>();
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
client.Blocking = true;
var dest = new DnsEndPoint(Hostname, Port);
_logger.LogInformation($"Attempting connection to {dest.Host}:{dest.Port}");
_logger.LogInformation($"Socket blocking: {client.Blocking}");
_logger.LogInformation("Calling BeginConnect");
var thd = client.BeginConnect(dest, new AsyncCallback(ConnectCallback), client);
_logger.LogInformation("BeginConnect complete");
_logger.LogInformation("Calling WaitOne");
finish.WaitOne(); // don't let program end until connection is made
_logger.LogInformation("WaitOne complete");
client.Close();
Thread.Sleep(25); // if you don't do this the program ends before all the log output can be written
Console.WriteLine("Program complete");
}
}
}
Я протестировал этот код с использованием .NET Core 2.1, и для его запуска вам понадобятся следующие пакеты nuget:
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console
Microsoft.Extensions.Logging.Debug"
Успешное выполнение выглядит следующим образом:
info: socketTst.Program[0]
Attempting connection to www.google.com:80
info: socketTst.Program[0]
Socket blocking: True
info: socketTst.Program[0]
Calling BeginConnect
info: socketTst.Program[0]
BeginConnect complete
info: socketTst.Program[0]
Calling WaitOne
info: socketTst.Program[0]
## ConnectCallback entered
info: socketTst.Program[0]
## Connection to server successful at 172.217.15.68:80
info: socketTst.Program[0]
## Data returned: HTTP/1.0 400 Bad Request
Content-Length: 54
Content-Type: text/html; charset=UTF-8
Date: Wed, 26 Sep 2018 03:32:39 GMT
<html><title>Error 400 (Bad Request)!!1</title></html>
Program complete