Проблемы с сокетом - PullRequest
       9

Проблемы с сокетом

0 голосов
/ 29 ноября 2011

Мой ответ:

После раздражения я нашел решение. Проблема заключалась в том, что в C # был либо сборщик мусора C #, либо многопоточность C #, он, вероятно, думал, что объект больше не нужен в потоке THAT, и удалил его. Решение было найдено следующим образом:

Я реализовал ClientThread в классе Server, передав объект Client в качестве параметров, и это небольшое изменение заставило его работать. Спасибо за все ваши ответы, если у кого-нибудь в будущем возникнет эта проблема, может быть, это не сборщик мусора в C #. Но многопоточность C # или сетевое взаимодействие должны выполняться внутри одного класса. Я сохранил свой клиентский класс и просто заставил объект потока запустить функцию внутри класса Server.

Если кто-то может понять, в чем заключалась моя проблема, не стесняйтесь комментировать, чтобы я мог расширить свои небольшие знания об управлении памятью в C #.

Еще раз спасибо всем, кто пытался помочь мне в этой теме.


Оригинальный вопрос

Я программист на C ++, поэтому я привык сам управлять памятью, и я действительно не уверен, как решить эту проблему.

Например, в C ++:

while(true)
{
    void* ptr = new char[1000];
}

Это была бы очевидная программа утечки памяти, поэтому мне нужно пойти дальше и очистить ее с помощью:

delete ptr;

Но бывают случаи, когда я хочу создать память для использования в другом потоке и не хочу, чтобы она была удалена после цикла.

while(true)
{
    socket.Accept(new Client());
}
//////////Client Constructor////////////
Client()
{
    clientThread.Start();
}

Этот фрагмент в основном то, что я хочу сделать в C #, но мой клиент подключается, а затем немедленно отключается, я предполагаю, что это потому, что в конце цикла while мой new Client() удаляется нашим любимым мусором Коллектор.

Итак, мой вопрос, как мне обойти это и заставить НЕ удалять мой объект.

Многие ответили, что говорили о том, что в коде есть другие ссылки на него. Я забыл упомянуть, что я также сохраняю нового клиента в списке клиентов, расположенных по всему миру

List<Client> clients;



//inside loop
clients.Add(new Client(socket.Accept()));

Хорошо, потому что я не уверен, что мне не хватает дополнительной информации, вот ФАКТИЧЕСКИЙ фрагмент кода

// Server class
    internal Socket socket { get; set; }
    internal Thread thread { get; set; }
    internal List<Client> clients { get; set; }
    internal void Init()
    {
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        thread = new Thread(AcceptThread);
    }
    internal void Start(int port,List<Client> clients)
    {
        var ipep = new IPEndPoint(IPAddress.Any, port);
        this.socket.Bind(ipep);
        this.socket.Listen(10);
        this.clients = clients;

        this.thread.Start();
    }
    internal void End()
    {
        socket.Close();
        thread.Abort();
    }
    internal void AcceptThread()
    {
        int ids = 0;

        while (true)
        {
            Client client = new Client();
            client.Init(socket.Accept());
            client.clientid = ids++;
            client.Start();
            clients.Add(client);
        }
    }

// Client class
public class Client
{
    .....

    #region Base Code

    internal void Init(Socket socket)
    {
        this.socket = socket;
        this.status = new SocketStatus();
        this.thread = new Thread(ClientThread);
        this.stream = new Stream();
    }
    internal void Start()
    {
        thread.Start();
    }
    internal void Close()
    {
        socket.Close();
        status = SocketStatus.Null;
        thread.Abort();
    }
    internal void ClientThread()
    {
        try
        {
            while (true)
            {
                byte[] data = new byte[1];
                int rec = socket.Receive(data);
                if (rec == 0)
                    throw new Exception();
                else
                    stream.write(data[0]);
            }
        }
        catch(Exception e)
        {
            Close();
        }
    }
    #endregion
}

Я благодарю вас за все ваши ответы.

Ответы [ 4 ]

2 голосов
/ 29 ноября 2011

Это совсем не так.Если существует какая-либо ссылка на экземпляр Client, который вы создали, то это не сборщик мусора.Это относится не только к вашему собственному коду.Поэтому, если GCing действительно является источником вашей проблемы, вы никогда не смогли бы получить к нему доступ в первую очередь!

Если вы не намеревались получить к нему доступ, вы в любом случае можете удержать их, вставивList.Тем не менее, я считаю, что как только вы действительно используете их в другой теме, о которой говорите, ваши проблемы исчезнут.

1 голос
/ 29 ноября 2011

С MSDN :

Если данные для чтения недоступны, метод получения будет блокироваться до тех пор, пока данные не станут доступны, если значение времени ожидания не было установлено с помощью сокета.ReceiveTimeout.Если значение тайм-аута было превышено, вызов Receive вызовет исключение SocketException.Если вы находитесь в неблокирующем режиме, и в буфере стека протоколов нет доступных данных, метод Receive завершится немедленно и выдаст исключение SocketException.Вы можете использовать свойство Available, чтобы определить, доступны ли данные для чтения.Если значение «Доступен» не равно нулю, повторите операцию приема.

Если вы используете сокет, ориентированный на подключение, метод получения будет считывать столько данных, сколько доступно, вплоть до размера буфера.Если удаленный хост завершает соединение Socket методом Shutdown, и все доступные данные были получены, метод Receive завершится немедленно и вернет нулевые байты.

Это, похоже, единственный способполучить возвращаемое значение 0 из метода Receive, а не получить исключение, поэтому может показаться, что все, что находится на другом конце, закрывает соединение.

1 голос
/ 29 ноября 2011

Я давно вышел из игры на c #, но не вижу в этом ничего плохого.Сборка мусора не должна начинаться до тех пор, пока на объекты больше не будут ссылаться.если ваш socket.Accept() не имеет ссылки, возможно, вы могли бы сделать это вручную:

var clients = new List<Client>();

while(true)
{
    client = new Client();
    clients.Add(client);
    socket.Accept(client);
}

////////// Client Constructor ////////////

Client()
{
    clientThread.Start();
}
0 голосов
/ 29 ноября 2011

Сборщик мусора удаляет только ресурсы, недоступные по какой-либо ссылке в вашей программе.Пока у вас есть переменная, которая ссылается на объект, он будет существовать.

...