Как остановить функцию socket.connect(), если она зависает?
Я сталкиваюсь с проблемой остановки функции socket.connect(). Иногда физическая связь между моей локальной машиной и удаленной машиной может быть хорошей, но по какой-то причине доступ к удаленной конечной точке невозможен, возможно, брандмауэр или порт на удаленной машине закрыты. В таких случаях функция socket.connection() застревает там и ждет бесконечно долгое время... Даже если брандмауэр отключен позже, функция все равно останется там навсегда.
Поэтому я попытался найти способ остановить socket.connect(), когда сталкиваюсь с вышеуказанными ситуациями.
Дело в том, что я использую.net микро-фреймворк, в котором у меня нет механизма тайм-аута или задачи, или socket.beginconnect();
Я пытаюсь сделать socket.connect() сам потоком и попытался прервать () его через 2 секунды, если (! Thread.join(2000)). Тем не менее, я не совсем понимаю функцию abort(), и я слышал, что это неразумный способ сделать это, и он не работает в конце концов.
Теперь я не знаю, что с этим делать? кто-нибудь может помочь? большое спасибо
main function
{
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//Set up socket
remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP_add), 30000);
m_socket.Connect(remoteEndPoint);
myThread.Start();
if (!myThread.Join(2000))
{
Debug.Print(myThread.ThreadState.ToString());
myThread.abort();
}
}
private static void socket_connect()
{
m_socket.Connect(remoteEndPoint);//Connect to remote device
}
2 ответа
Было предложено иметь Connect
тайм-аут вызова занятым ожиданием. Я категорически не согласен с а) этой философией и б) утверждением, что WinSock не предлагает лучшего способа решения этой общей проблемы.
Вот лучшее решение:
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
socket.Close();
});
try
{
socket.Connect("192.168.2.123", 1234);
}
catch (SocketException sex)
{
if (sex.ErrorCode == 10038)
Console.WriteLine("Timeout");
else
throw;
}
}
Вы сами определяете время ожидания и закрываете розетку. Эта программа запускается около 1 секунды, чтобы сработал механизм тайм-аута.
Обратите внимание, что приведенный выше код является демонстрационным кодом и должен использовать таймер и быть свободным от гонки.
Что плохого в занятом ожидании?
- Плохо поддерживать
- Вводит задержку
- Perf-проблема в случае множества сокетов. Полностью не стартер на серверных системах
- На клиентах ЦП не может выключиться, и вы сжигаете батарею
Если ваша платформа поддерживает неблокирующие соединения, вы можете попробовать этот код. Я написал это для.net 4 в Win7.
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Console.WriteLine("Trying to connect");
socket.Blocking = false;
try
{
socket.Connect("8.8.8.8", 5050);
}
catch (Exception ex)
{
if (ex is SocketException) && ((SocketException)ex).ErrorCode == 10035) // There is a socket problem and this problem is because of being in non-blocking mode? Then this is just a warning
{
// Waiting for connection
int time = 0;
while (time < 1000) // If it was lower than 1 second
{
// Do what you want
if (socket.Connected) // If connected then break
break;
System.Threading.Thread.Sleep(50); // Wait 50milisec
time += 50;
}
}
else
{
Console.WriteLine("Failed");
}
}
if (!socket.Connected)
Console.WriteLine("Aborted");
else
Console.WriteLine("Connected");