Tcpclient/server

  • Автор темы WildDuck
  • Дата начала
W

WildDuck

#1
Добрый вечер! Возникла проблема с событием disconnect.. его просто нет в классах TcpClient/TcpServer.. кто-нибудь знает как лучше его организовать? в итоге нужно сделать так, чтобы при внезапном разрыве соединения, второе приложение сразу об этом узнало!
 
P

Pasha

#2
Для: WildDuck
При внезапном разрыве соединения ты получишь IOException или SocketException при следующей попытке чтения/записи. А то, что события нет - недостатки самих сокетов. :D
 

Kmet

Java Team
25.05.2006
1 036
8
#3
вообщето у TCP есть фенечка KEEP_ALIVE, вот только далеко не все реализации ее поддерживают =(
 
P

Pasha

#4
Начиная с win2k поддерживается, из .net можно включить через SetSocketOption. Вот только о разрыве соединения все равно узнаешь при попытке передачи данных :)
 
W

WildDuck

#5
а как же тогда.. получается что нельзя полноценно использовать сокеты !? :)
Хотябы KEEP_ALIVE ;) неособо удобно, но хотябы так. Спасибо!

Нашол статейку вроде бы можно ... http://www.rsdn.ru/article/net/keep_alive.xml (Определение разрыва TCP-соединения) там все основано я так понимаю на том, что идет постоянное перепингивание.. :) а когда ответа нет, значит дисконект...
 
P

Pasha

#6
Для: WildDuck
Хм. Что значит "полноценно использовать сокеты"? Сами сокеты так устроены, что узнать о разрыве соединения можно только при попытке передачи. :)
 
W

WildDuck

#7
Вы имеете ввиду не реализация в .net , а вообще все сокеты так устроены?
 

Kmet

Java Team
25.05.2006
1 036
8
#8
<!--QuoteBegin-Pasha+19:11:2007, 15:53 -->
<span class="vbquote">(Pasha @ 19:11:2007, 15:53 )</span><!--QuoteEBegin-->Сами сокеты так устроены, что узнать о разрыве соединения можно только при попытке передачи.
[snapback]86453" rel="nofollow" target="_blank[/snapback]​
[/quote]
полагаю это справедливо только для блокирующих сокетов. в случае работы с сокетами в событийной модели по идее KEEP_ALIVE должен работать.
 
P

Pasha

#9
Для: Kmet
Для н*цензура*кирующих сокетов то же самое. Подразумевается что клиент сначала явно попытается прочитать данные, а потом уже получит о разрыве соединения.
 

Kmet

Java Team
25.05.2006
1 036
8
#10
<!--QuoteBegin-WildDuck+19:11:2007, 15:18 -->
<span class="vbquote">(WildDuck @ 19:11:2007, 15:18 )</span><!--QuoteEBegin-->[snapback]86451" rel="nofollow" target="_blank[/snapback]</div>[/quote]
если верить исходникам статьи, работает
 
P

Pasha

#11
Для: Kmet
Там делается примерно следующее:
Создается событие
WSAEventSelect(sock, hEvents[1], FD_CONNECT|FD_READ|FD_CLOSE);
Потом оно ожидается
WaitForMultipleObjects (2, hEvents, FALSE, INFINITE);
в случае, если события дождались, идет гадание по WSAEnumNetworkEvents, чего же именно дождались.
Этот код заменяется на Socket.BeginReceive, и гадание по IAsyncResult. Проблема только в том, что event в этом коде - не событие в смысле .net. Событие в .net - это callback в C++. А сокеты не поддерживают callbacks.
 
W

WildDuck

#12
В принцепи нашол банальный выход..свое событие -- while { чтение из сокета } если ошибка значит дисконект...

По поводу событий у меня появился небольшой вопросик..
Имею свое событие, допустим которое срабатывает после того
как ко мне что-то пришло в сокет.. В общей части программы
в пришедшем событии пишу допустим RichTextBox.text += TEXT;
вылазиет исключение....пишет что нет доступа к RichTextBox,
хотя подобный пример в другой программе работает, если быть
точнее то он и в этой программе работает, и в этом событии)
только вызванное другой функцией.. со стороны клиента,
код один к одному фактически.
Может быть при описании событий есть какая-нибудь хитрость?))

заранее благодарен!
 
W

WildDuck

#13
Код:
public partial class Form1 : Form
{
ConnectTCP сonnectTCP = new ConnectTCP();

public Form1()
{
InitializeComponent();
сonnectTCP.readData += new ConnectTCP.ReadDataTCP(сonnectTCP_readData);
}

..... разные методы....

void сonnectTCP_readData(string messageData)
{
richTextBox1.Text += messageData;
}

}


public class ConnectTCP
{
public delegate void ReadDataTCP(string messageData);
public event ReadDataTCP readData;

protected void OnDataRead(string messageData)
{
try
{
...... проверка пришедших данных

readData(messageData);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());  ... вот это то то исключение и срабатывает!
// invalidOperationExcaption RichTextBox1.... access from a Thread ..
}
}

клиент по приходу сообщения вызывает
OnDataRead(сообщение)

сервер по приходу сообщения вызывает
OnDataRead(сообщение)

}
пока писал это сообщение разобрался... просто сервер был запущен через VS... спасибо!

(выложил может кому поможет)
 
P

Pasha

#14
Для: WildDuck
На самом деле проблема была в том, что richTextBox1.Text += messageData не из того потока, в котором он был создан. Уже не раз обсуждалось, поищи по форуму слово Invoke.