гайка
Гость
|
|
« : 18-07-2012 11:47 » |
|
Товарищи, кто мне может объяснить, почему к объекту Socket нельзя подключиться в обычном (синхронном) режиме, если соединение было разорвано? или если первая попытка подключения была безуспешной.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #1 : 18-07-2012 14:37 » |
|
Гайка, непонятно, что значит "подключиться в синхронном режиме"? Либо сам сокет подключается к чему-то на другой стороне, либо он принимает чьё-то соединение с другой стороны.
Код, который не работает, сюда.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
гайка
Гость
|
|
« Ответ #2 : 20-07-2012 09:08 » |
|
Да, прости, я неправильно сказала. не "подключиться", а "подключить". у Socket есть 2 способа подключения: 1) метод Connect, он работает в текущем потоке и, если порт недоступен, по истечению таймаута выдает исключение 2) метод BeginConnect, он работает в другом потоке и по завершению работы возвращается к текущему потоку, а именно к тому методу, который указан в параметре. да, я сама знаю, что я кэп. так вот, если порт доступен, то подключение выполняется нормально. а если порт становится недоступным (в моем случае, если вытаскивается из розетки устройство, открывающее tcp порты) на какое-то время, а потом снова открывается, то доступ к нему уже не получить ни одним из этих методов.
и да, в моем случае, сокет только сам подключается к чему-то, но не принемает входящие подключения.
код бы нежелательно выкладывать, это рабочий проект.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #3 : 20-07-2012 10:56 » |
|
код бы нежелательно выкладывать, это рабочий проект. У меня правило все такие сомнительные вещи отрабатывать на небольших прототипах - консольных программках, и только потом переносить отлаженный код в рабочий проект. А так беспредметно говорим. Если посмотреть MSDN для BeginConnect, там такая масса ньюансов, что без кода гадать бесполезно.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
гайка
Гость
|
|
« Ответ #4 : 20-07-2012 13:01 » |
|
public class Base : Singleton<Base> { List<Gateway> _gateways;//список шлюзов public List<Gateway> Gateways { get { return _gateways; } set { _gateways = value; } }
List<TCPConnection> _connections;//список всех подключений public List<TCPConnection> Connections { get { return _connections; } set { _connections = value; } }
static int _refreshingInterval = 7000;//интервал обновления соединения public static int RefreshingInterval { get { return Base._refreshingInterval; } set { Base._refreshingInterval = value; } }
System.Timers.Timer _refreshingTimer;//таймер для обновления public System.Timers.Timer RefreshingTimer { get { return _refreshingTimer; } set { _refreshingTimer = value; } }
private Base() { _gateways = new List<Gateway>(); _connections = new List<TCPConnection>(); _refreshingTimer = new System.Timers.Timer(_refreshingInterval); _refreshingTimer.Elapsed += new ElapsedEventHandler(_refreshingTimer_Elapsed); _refreshingTimer.Enabled = false; //....................................
}
void _refreshingTimer_Elapsed(object sender, ElapsedEventArgs e) { RefreshConnections(); }
public void ConnectToAllPorts() { foreach (Gateway g in _gateways) for (int i = g.MinPort; i <= g.MaxPort; i++) { TCPConnection con_ = new TCPConnection(g.IpAddress, i); if (con_.State != ConnectionState.Error) _connections.Add(con_); } _refreshingTimer.Start(); }
public void CloseAllConnections() { foreach (TCPConnection c in _connections) { try { c.Socked.Disconnect(true); } catch { } c.Socked.Close(); } _connections.Clear(); _refreshingTimer.Stop(); }
public void RefreshConnections() { foreach (TCPConnection c in _connections) { Thread t_ = new Thread(c.Refresh); t_.Start(); } } public enum ConnectionState { Error=0, Empty, Online, Offline }; //устройство на том конце может быть включено\выключено\не подключено\не существует, т.к. порт недоступен public class TCPConnection { /// <summary> /// Максимальное время ожидания отклика от устройства после отправки и чтения данных /// </summary> static int _maxResponseTimeout = 5000; public static int MaxResponseTimeout { get { return _maxResponseTimeout; } set { _maxResponseTimeout = value; } }
static int _minResponceTimeout = 50; public static int MinResponceTimeout { get { return _minResponceTimeout; } set { _minResponceTimeout = value; } }
Socket _socked; public Socket Socked { get { return _socked; } set { _socked = value; } }
ConnectionState _state; public ConnectionState State { get { return _state; } set { _state = value; } }
IPAddress _gatewayIPAddress; public IPAddress GatewayIPAddress { get { return _gatewayIPAddress; } set { _gatewayIPAddress = value; } }
int _portNumber; public int PortNumber { get { return _portNumber; } set { _portNumber = value; } }
public TCPConnection(IPAddress ipAddress, int port) { _socked = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _gatewayIPAddress = ipAddress; _portNumber = port; _state = ConnectionState.Empty; try { _socked.Connect(ipAddress, port); Refresh(); } catch { _state = ConnectionState.Error; } } public void Refresh() { byte[] message_; try { if (_socked.Connected) message_ = ATSMessages.Instance.GetPocket; else { //тут создается новый сокет, т.к. попытки оживить старый ни к чему не привели _socked = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socked.Connect(_gatewayIPAddress, _portNumber); //впрочем, это тоже не приводит к нужному результату message_ = ATSMessages.Instance.LogOn; } if (Responds(message_)) _state = ConnectionState.Online; else { if (_socked.Connected) _state = ConnectionState.Offline; else _state = ConnectionState.Empty; } } catch { _state = ConnectionState.Error; } }
bool Responds(byte[] message) { //тут проверка на то, отвечает ли устройство на посылаемые пакетики } } тут вариант без заморочек, в Refresh() используется обычный Connect.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #5 : 20-07-2012 14:22 » |
|
Гайка, у меня и другое правило есть: выкидывать из прототипа всё, что не относится к проблеме. Здесь какой-то пул соединений, которым чёрт знает как пользоваться. И явно вся эта "ботва" с пулом не может иметь отношения к тому, с чего ты начала. Если же отдельно взятое соединение работает, то тогда и проблема в другом. тут вариант без заморочек, в Refresh() используется обычный Connect. И зачем мне код, в котором нет проблем? Не пойму я тебя.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
гайка
Гость
|
|
« Ответ #6 : 20-07-2012 14:50 » |
|
"без заморочек" не означает "без проблем". тут не используется асинхронное подключение, вот что имелось ввиду. А начну вырезать куски кода, ты скажешь, что не видишь общей картины. Смотри. у меня есть устройство (и это именно физическое устройство с физическими портами), открывающее доступ к множеству других устройств через TCP. оно как переводчик. если у него выключено питание, то никакого доступа к портам быть не может. в том коде в ф-ции Refresh() я пыталась создать новый сокет и подключиться к нему, в том случае, если соединение было по какой-то причине прервано. заново оно не устанавливается. вылетает ошибка.
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #7 : 20-07-2012 15:01 » |
|
Гайка, просто неприятно, когда человек не может словами рассказать, что же он делает. Смотри. у меня есть устройство (и это именно физическое устройство с физическими портами), открывающее доступ к множеству других устройств через TCP. оно как переводчик. если у него выключено питание, то никакого доступа к портам быть не может. Хорошо. Это понятно. в том коде в ф-ции Refresh() я пыталась создать новый сокет и подключиться к нему, в том случае, если соединение было по какой-то причине прервано. заново оно не устанавливается. вылетает ошибка. По-твоему в твоём коде написано то, что ты говоришь? Ну вот код, который синхронно и асинхронно пробует подключиться к недоступному адресу. using System; using System.Net; using System.Net.Sockets;
namespace testtcp { class MainClass { private const int Timeout = 1000; private static IPEndPoint Point = new IPEndPoint(new IPAddress(new byte[] {1, 2, 3, 4}), 80); private static void TestSync() { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.ReceiveTimeout = Timeout; socket.SendTimeout = Timeout; Console.WriteLine("A socket is created."); try { socket.Connect(Point); Console.WriteLine("A socket is connected."); } catch(Exception exception) { Console.WriteLine("Exception: " + exception.Message); } socket.Close(); Console.WriteLine("A socket is closed."); } private static void TestAsync() { Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.ReceiveTimeout = Timeout; socket.SendTimeout = Timeout; Console.WriteLine("A socket is created."); try { socket.BeginConnect(Point, new AsyncCallback(Callback), socket); Console.WriteLine("A socket is been connecting."); } catch(Exception exception) { Console.WriteLine("Exception: " + exception.Message); } } private static void Callback(IAsyncResult result) { Socket socket = result.AsyncState as Socket; try { socket.EndConnect(result); Console.WriteLine("A socket is connected."); } catch(Exception exception) { Console.WriteLine("Exception: " + exception.Message); } socket.Close(); Console.WriteLine("A socket is closed."); } public static void Main (string[] args) { TestSync(); TestAsync(); Console.WriteLine("Press any key for exit."); Console.ReadKey(); } } } В обоих случаях результат абсолютно одинаковый. P.S. У тебя я не вижу ни вызова Close, как в приличных домах, ни тем более обработки многочисленных исключительных ситуаций, подробно описанных в MSDN.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
гайка
Гость
|
|
« Ответ #8 : 20-07-2012 15:04 » |
|
Дима, слушай, ну почему ты не можешь ответить, не вылив на меня предварительно бочку дерьма?
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #9 : 20-07-2012 15:47 » |
|
Гайка, потому что я был вынужден написать эту программу. И, судя по всему, вынужден буду писать её дальше до тех пор, пока твой пул соединений не будет переписан радикальным образом.
Тема сродни в "Срочно пАмАгите", только на более высоком уровне - на следующей ступеньке профлесницы. Там приходит халявщик, пишет задание и чужой код, говорит при этом, что ничего не знает, не понимает, решайте, мол. Ты, конечно, знаешь кое-что, ты пишешь свой код. Но проблема та же самая на другом уровне - на уровне инженерии, архитектуры. Т.е. мне нужно либо спроектировать тебе этот пул потоков с учётом обработки исключительных ситуаций и многопоточности (затратить на это полдня-день), либо молчать в тряпочку. Твоя проблема кодированием или волшебным оператором не решается. Ты этого, похоже, не понимаешь, а мне эта ситуация неприятна.
Разговор будет конструктивным, если ты отложишь свою основную задачу, создашь консольный прототип и начнёшь шаг за шагом, строчка за строчкой оформлять решение, внимательно читая MSDN и тестируя промежуточные результаты. Это будет инженерия, процесс проектирования.
Понятно объяснил?
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
|