Правильный способ прекратить прослушивание сокета
У меня есть сервер, который слушает подключение к сокету:
public class Server
{
private Socket _serverSocket;
public Server()
{
_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_serverSocket.Bind(new IPEndPoint(IPAddress.Any, 1234));
_serverSocket.Listen(1);
}
public void Start()
{
_serverSocket.BeginAccept(HandleAsyncConnectionMethod, null);
}
public void Stop()
{
//????? MAGIC ?????
}
//... rest of code here
}
Каков правильный (чистый) способ закрыть сокет?
Достаточно ли вызвать:
_serverSocket.Disconnect(true);
в методе Stop()? или есть ли другая работа, которая должна произойти, чтобы закрыть соединение чисто?
Ответы
Ответ 1
Прекращение TCP-соединения правильно включает в себя четырехстороннее рукопожатие. Вы хотите, чтобы оба конца сообщали другому, что они завершают работу, а затем подтверждают друг друга.
Википедия объясняет этот процесс: http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_termination
В этом сообщении объясняется, как сделать это на С#: http://vadmyst.blogspot.com/2008/04/proper-way-to-close-tcp-socket.html
Ответ 2
Поскольку вы слушаете входящие TCP-соединения, вы можете использовать System.Net.Sockets.TcpListener, который имеет метод Stop(). Тем не менее, он не имеет асинхронных операций.
Ответ 3
2 способа закрыть его без исключений
1) создайте временный соединительный сокет и подключите его к прослушиванию, чтобы он мог запускать его обработчик, а затем просто закончил его с помощью обычного EndAccept и после этого закройте оба.
2) просто закройте (0) прослушивающий сокет, который приведет к ложному срабатыванию его обратного вызова, если вы затем заглянете в свой слуховой сокет, вы увидите, что его состояние "закрыто" и "расположено". Вот почему вызов EndAccept вызывает исключение. Вы можете просто игнорировать его и не называть EndAccept. Слушающий сокет сразу же отключается без тайм-аута.
Ответ 4
Самый чистый способ немедленного прерывания вызова Accept - вызов _serverSocket.Dispose();
Любые другие вызовы методов, подобных Shutdown или Disconnect, вызывают исключение.
Ответ 5
Вы должны использовать Socket.Shutdown(), а затем Socket.close(). Socket.Disconnect() обычно используется только в том случае, если вы намерены повторно подключить один и тот же сокет.
Ответ 6
Во-первых, вам нужно убедиться, что вы отслеживаете любые клиентские сокеты, созданные в процессе BeginAccept. Сначала закройте их, используя методы Socket.Shutdown() и Socket.Close(). После того, как все они были закрыты, выполните то же самое в самом гнезде прослушивания.
Ответ 7
Это должно справиться с этим... но если вам нужно быть абсолютно уверенным, вы всегда можете убить его огнем:
Не для сокетов, но такая же идея применяется., которая должна закрыть его всеми возможными способами, а затем, наконец, установить сокет в null.