c # странность сети - PullRequest
0 голосов
/ 23 января 2012

Я работаю на небольшом сетевом сервере и делаю это из последней версии MonoDevelop.

У меня есть метод PlayerReadLoop, который передает тривиальный объект Player, а также передает объект tcpClient. Этот метод еще не завершен и не зависит от объекта Player, которому он передается, поэтому нет необходимости предоставлять какую-либо информацию об игроке. TcpClient определенно инициализирован должным образом, поскольку мне удалось передать сообщения через этот tcpClient.

Вот метод:

private void playerReadLoop(Player p, TcpClient c)
{
    byte[] message = new byte[4096];
    int bytesRead;
    NetworkStream clientStream = c.GetStream();
    while (true)
    {
        bytesRead = 0;
        try
        {
            bytesRead = clientStream.Read(message, 0, 4096);
        }
        catch
        {
            Console.WriteLine("ERROR");
            break;
        }
        if (bytesRead == 0)
        {
            Console.WriteLine("Disconnected");
            break;
        }

        ASCIIEncoding encoder = new ASCIIEncoding();
        Console.WriteLine(encoder.GetString(message, 0, bytesRead));

    }
}

По какой-то причине вышеприведенный код не работает! Вы видите,

Когда я окружаю две линии:

SCIIEncoding encoder = new ASCIIEncoding();
Console.WriteLine(encoder.GetString(message, 0, bytesRead));

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

Когда две строки НЕ записываются, clientStream.read НИКОГДА не проходит. Отправляет ли мой клиент сообщение.

Теперь, если это не было достаточно странно, имея приведенный выше код ПРЯМО после моей инициализации tcpClient (в том же методе, который был инициализирован tcpClient), код РАБОТАЕТ! Я ничего не делаю с tcpClient, я просто передаю это непосредственно в функцию выше, с объектом Player, который был инициализирован с помощью tcpClient. Объект player ничего не делает с tcpClient, он просто сохраняет его в одной из своих переменных. Я не понимаю, как простой акт помещения этого кода в его собственный метод вызывает такое непристойное различие в поведении!

Код клиента прост:

TcpClient client = new TcpClient();

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 21255);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

Ответы [ 2 ]

0 голосов
/ 23 января 2012

Источник;http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.flush.aspx

Вызов Flush для сетевого потока не имеет никакого эффекта, поэтому его не должно быть в вашем коде для начала.

Операции чтения и записи обычно блокируют операции наРозетки.Таким образом, они будут ждать, пока операция не будет полностью завершена.Перед чтением и записью в сетевой поток лучше проверить, действительно ли они могут быть записаны или прочитаны.Есть свойства для этого.(дополнительная информация на http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.write.aspx)

Кроме того, поскольку Read может возвращать 0, это не означает, что клиент "отключен", как написано в вашем коде. Это просто означает, что в приемном буфере еще нет доступных байтов дляread from. Это также означает, что Read будет блокировать по умолчанию, пока данные фактически не отправляются.

Если вы не получаете данные, проверьте параметры порта и соединения на клиенте и сервере, чтобы они соответствовали.

РЕДАКТИРОВАТЬ То, что вы что-то записываете в сетевой поток, не означает, что оно отправляется напрямую по проводам. Между вашим кодом и реальным сокетом есть буфер. Нет контроля над этим буферомЭто контролируется только Windows. Вот почему иногда возникает задержка между вашим кодом и фактической отправкой.

Это также объясняет, почему некоторые настройки или конфигурация кода, кажется, не оказывают прямого влияния. Эта информация хорошо скрытаи не на MSDN, но если вы погрузитесь в технические документы Microsoft о сокет коммьюнитиКатион, вы найдете много более сочных кусочков, которые объясняют это.К сожалению, сейчас я не могу поделиться ссылкой.

0 голосов
/ 23 января 2012

Я работаю на небольшом сетевом сервере

Вы сталкивались с библиотекой сетевых коммуникаций c # с открытым исходным кодом networkComms.net ?Это так же хорошо, как подключи и играй, так что вы можете сразу начать работу.Кроме того, большинство проблем, с которыми вы столкнетесь, уже решены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...