Не удается повторно привязать сокет к существующей комбинации IP / порта - PullRequest
4 голосов
/ 07 сентября 2008

Привет, я пытаюсь найти способ «отсоединить» сокет от определенной комбинации IP / порта. Мой псевдокод выглядит так:

ClassA a = new ClassA(); //(class A  instantiates socket and binds it to 127.0.0.1:4567) 
//do something 
//...much later, a has been garbage-collected away.
ClassA aa = new ClassA(); //crash here.

На данный момент .Net сообщает мне, что у меня уже есть сокет, связанный с 127.0.0.1:4567, что технически верно. Но независимо от того, какой код я поместил в деструктор ClassA, или независимо от того, какие функции я вызываю в сокете (я пробовал .Close () и .Disconnect (true)), сокет остается гордо связанным с 127.0.0.1:4567. Что мне делать, чтобы иметь возможность «отсоединить» сокет?


РЕДАКТИРОВАТЬ: я не полагаюсь исключительно на сборку мусора (хотя я тоже пробовал этот подход). Я попытался вызвать a.Close () или a.Disconnect () и только затем создать экземпляр aa; это не решает проблему.


РЕДАКТИРОВАТЬ: Я также пытался реализовать IDisposable, но код не получил там без моего вызова метода (что было эквивалентно более ранним попыткам, так как метод будет просто пытаться .Close и .Disconnect). Позвольте мне попробовать позвонить. Уничтожить напрямую и вернуться к вам.


РЕДАКТИРОВАТЬ (много правок, извинений): Реализация IDisposable и вызов a.Dispose (), из-за которого «a» теряет область видимости, не работает - моя реализация Dispose все равно должна вызывать либо .Close, либо .Disconnect (true) ( или .Shutdown (Оба)), но ни один из них не отвязывает сокет.

Буду признателен за любую помощь!

Ответы [ 5 ]

3 голосов
/ 07 сентября 2008

(это то, что, наконец, заставило меня работать)

Убедитесь, что КАЖДЫЙ разъем, к которому подключается разъем A, имеет

socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress, true);

устанавливается при инициации.

0 голосов
/ 30 сентября 2009

Лучшее решение - повторить попытку связать сокет несколько раз (2-3). С первой попытки, если она не удалась, я обнаружил, что она правильно (и навсегда) закроет исходный сокет.

НТН,

_NT

0 голосов
/ 07 сентября 2008

Сборщик мусора не гарантирует, что сокет когда-либо будет закрыт. Для полного примера прочитайте этот пример MSDN .

Суть в том, чтобы на самом деле позвонить Socket.Close() как можно скорее. Например, ClassA может реализовать IDisposable и использовать его так:

using (ClassA a = new ClassA()) 
{
    // code goes here
}
// 'a' is now disposed and the socket is closed
0 голосов
/ 07 сентября 2008

Сборщик мусора запускает финализатор объекта в неопределенное время. Вы можете реализовать интерфейс IDisposable и вызвать метод Dispose () до того, как объект потеряет Scope, или позволить оператору using сделать это за вас.

см. http://msdn.microsoft.com/en-us/library/system.idisposable.aspx и http://msdn.microsoft.com/en-us/library/yh598w02.aspx

edit: у меня отлично работает

using System;
using System.Net.Sockets;
using System.Net;

namespace ConsoleApplication1
{
    class Program
    {
        class ClassA : IDisposable
        {
            protected Socket s;
            public ClassA()
            {
                s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Bind(new IPEndPoint(IPAddress.Any, 5678));
            }

            public void Dispose()
            {
                s.Close();
            }
        }

        static void Main(string[] args)
        {
            using(ClassA a=new ClassA()) {
            }
            using (ClassA b = new ClassA())
            {
            }
        }
    }
}
0 голосов
/ 07 сентября 2008

вы не можете полагаться на сборку мусора в C # (я предполагаю, что вы используете c #, основываясь на тегах), если он содержит ресурсы, такие как привязка к сетевому ресурсу, как в вашем примере, или хранение какого-либо другого вида поток, поток файла будет общим примером.

Вы должны обеспечить освобождение ресурсов, которые содержит объект, чтобы его можно было собирать мусором. иначе это не будет мусор, но останется где-то в памяти. ваш пример псевдокода не предусматривает, что вы делаете освобождение ресурсов, вы просто заявляете, что объект получает (должен получать) мусор.

...