| 
			| 
					
						| гайка 
								Гость
 | 
								|  | «  : 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 и тестируя промежуточные результаты. Это будет инженерия, процесс проектирования.
 
 Понятно объяснил?
 |  
						| 
								|  |  
								|  |  Записан | 
 
 Программировать - значит понимать (К. Нюгард)Невывернутое лучше, чем вправленное (М. Аврелий)
 Многие готовы скорее умереть, чем подумать (Б. Рассел)
 |  |  | 
	|  |