Итак, я знаю, что есть много статей по этой теме, и я прочитал много из них, я бы сказал, но по какой-то причине я уверен, что мой код не делает то, что должен делать.
Я хочу закрыть соединение между моим сервером и моим клиентом. Теперь на стороне сервера я запускаю отключение с помощью этого кода
public void shutdown()
{
_socket.Shutdown(SocketShutdown.Both);
_socket.Close();
}
И на стороне клиента у меня есть некоторые проблемы с пониманием того, как я добираюсь до отключения, что, как я считаю, происходит следующим образом: в моем асинхронном обратном вызове получения я должен получить сообщение об ошибке, так как сервер запустил последовательность отключения, и я должен обработать это (верно ???), поэтому мой код для клиента выглядит так: ReceiveCallback:
private void ReceiveCallback(IAsyncResult result)
{
int bytesRecieved = 0;
byte[] tempBuff;
//Try to receive But if a Socket error occures disconnect otherwise start Receiving again
try
{
bytesRecieved = _socket.EndReceive(result);
}
catch (SocketException sockEx)
{
Disconnect(sockEx);
return;
}
catch (ObjectDisposedException disposeEx)
{
Disconnect(disposeEx);
return;
}
catch (Exception ex)
{
StartReceive();
return;
}
if (bytesRecieved == 0)
{
StartReceive();
return;
}
tempBuff = new byte[bytesRecieved];
Buffer.BlockCopy(_buffer, 0, tempBuff, 0, bytesRecieved);
StartReceive();
_packHandler.handlePacket(tempBuff);
}
Отключить:
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
DisconnectCallback
private void DisconnectCallback(IAsyncResult result)
{
_socket.EndDisconnect(result);
_socket.Close();
}
(Метод Disconnect перегружен, поэтому, если я получаю исключение, он создает messageBox, а затем также вызывает Disconnect. Просто чтобы я знал, что произошло.)
В чем я ошибаюсь и что можно улучшить?
Я попробовал код, и, похоже, он работал, но затем я посмотрел с помощью netstat, все ли сокеты закрыты, а клиентский - нет. Это было в FIN_WAIT_2, что означает, что он (или сервер ???) еще не отправил пакет FIN, верно? О, а потом я попробовал еще раз, изменив эту строку:
if (bytesRecieved == 0)
{
StartReceive();
return;
}
К
if (bytesRecieved == 0)
{
Disconnect;
return;
}
Который затем вызвал исключение на стороне сервера, а на стороне клиента клиент сказал, что соединение было закрыто сервером ???
РЕДАКТИРОВАТЬ: Даже когда я закрыл обе программы, Netstat все еще показывает порт в состоянии ОЖИДАНИЕ. что это мне говорит?
2 ответа
Важно:
- Если сервер запускает последовательность выключения, вам НЕОБХОДИМО обработать это
- Обе стороны должны вызвать отключение на своем сокете.
- Вам нужен способ заметить отключение (это не дает вам ошибки или, по крайней мере, не для меня)
Поэтому я создал свой собственный класс customSocket, который наследуется от Socket
public class customSocket : Socket
{
#region Properties
private readonly Timer _timer;
private const int _interval = 1000;
private bool Connected
{
get
{
bool part1 = Poll(1000, SelectMode.SelectRead);
bool part2 = (Available == 0);
if (part1 && part2)
return false;
else
return true;
}
}
public bool EventsEnabled
{
set
{
if (value)
{
_timer.Start();
}
else
_timer.Stop();
}
}
#endregion
#region Constructors
public customSocket(AddressFamily addressFamily, SocketType sockType, ProtocolType protocolType)
: base(addressFamily, sockType, protocolType)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
public customSocket(SocketInformation sockInfo)
: base(sockInfo)
{
_timer = new Timer { Interval = _interval };
_timer.Elapsed += TimerTick;
}
#endregion
#region Events
public event EventHandler<EventArgs> Socket_disconected;
public void Raise_Socket_disconnected()
{
EventHandler<EventArgs> handler = Socket_disconected;
if (handler != null)
{
handler(this,new EventArgs());
}
}
private void TimerTick(object sender, EventArgs e)
{
if (!Connected)
{
Raise_Socket_disconnected();
}
}
#endregion
}
Эта версия сокета имеет Событие для отключения. Теперь, если вы создаете экземпляр своего класса сокета, вам нужно подключить обработчик и установить для EventsEnabled значение true.
Затем этот обработчик вызывает завершение работы, и ваш сокет не остается в FIN_WAIT_2
У вашего обычного отключения есть выключение, которое очищает сокет, чтобы он мог правильно отключиться, но ваш асинхронный стиль никогда не вызывает выключение. Я добавил его в удобном месте ниже.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
_socket.Shutdown(SocketShutdown.Both); // Make sure to do this
_socket.BeginDisconnect(false, DisconnectCallback, null);
}
РЕДАКТИРОВАТЬ:
Судя по звукам, у вас нет причин использовать асинхронный метод? Асинхронные методы позволяют отправлять данные в отдельном потоке выполнения, освобождая поток, например, для выполнения некоторой обработки данных, пока это происходит.
Я не вижу какой-либо обработки, поэтому предлагаю вам изменить отключение таким образом и посмотреть, решит ли это проблему. Потому что я не думаю, что вы ждете асинхронных методов, которые не сработают.
public void Disconnect()
{
if (!_socket.Connected)
{
return;
}
shutdown(); //Your standard disconnect that you showed up top. Scoping might be required.
}
Немного данных об Async можно найти здесь: http://msdn.microsoft.com/en-us/library/38dxf7kt(v=vs.110).aspx
Похожие вопросы
Новые вопросы
c#
C# (произносится как «see Sharp») — это высокоуровневый мультипарадигменный язык программирования со статической типизацией, разработанный Microsoft. Код C# обычно нацелен на семейство инструментов и сред выполнения Microsoft .NET, которое включает в себя .NET, .NET Framework, .NET MAUI и Xamarin среди прочих. Используйте этот тег для ответов на вопросы о коде, написанном на C#, или о формальной спецификации C#.