Сокет только получает часть сообщения C # - PullRequest
1 голос
/ 09 мая 2009

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

byte[] buffer = new byte[10240];
//...
sock.Receive(buffer);
string response = message(buffer);
Console.WriteLine("Message Recieved");
if (!verifyUser(response, sock))
Console.WriteLine("User Invalid");
//...
static private bool verifyUser(string userString, Socket sock)
{
   string[] userData = userString.Split(' ');
   int i = 0;
   while (true)
    {
        if (userData[0].ToUpper() != "USER")
        {
           byte[] buffer = message("WHO");
           sock.Send(buffer);
           userData = userString.Split(' ');
           i++;
           if (i > 4)
           {
                        return false;
                    }
                    continue;
                }
                else
                    break;
            }
Console.WriteLine("Connection recieved from " + userData[1] + " with hash of "/* + userData[2]*/);
}

Проблема, с которой я столкнулся, заключается в том, что, если я отправляю имя пользователя unkwntech, все, что отображается, выводится на экран unkwnt, а второе значение, похоже, никогда не появляется. приложение, отправляющее данные, выглядит так:

static void Main(string[] args)
        {
            Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            EndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200);
            sock.Connect(remoteEP);
            byte[] buffer = Encoding.ASCII.GetBytes("USER unkwntech a3f5h4a35sfg");//Made up hash
            sock.Send(buffer);
            sock.Receive(buffer);
            Console.WriteLine(Encoding.ASCII.GetString(buffer));
            Console.ReadLine();
        }

Ответы [ 2 ]

7 голосов
/ 09 мая 2009

Вы , предполагая , что когда вы отправляете, все данные заканчиваются в одном пакете, и что вы получите все данные за один раз на другом конце. Это не так, как работает TCP / IP. Это потоковый протокол - вы никогда не должны делать предположения о том, сколько данных вы получите за один раз.

Обычно вам нужно читать из потока, пока вы не прочитаете все данные и сокет не будет закрыт, или пока у вас не будет "достаточно" данных. Если вы контролируете протокол и он является протоколом для разговоров, он намного упрощает жизнь, если каждое отправляемое сообщение имеет префикс по длине - это означает, что другой конец знает, сколько данных ожидать.

1 голос
/ 09 мая 2009

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

Если в вашем протоколе каждое сообщение имеет префикс по длине, для полной пуленепробиваемости ваш протокол должен также определить байт маркера, чтобы отметить конец заголовка длины с префиксом. Читайте по одному байту за раз, пока не увидите байт маркера. Затем рассчитайте длину сообщения и читайте большими кусками, пока не прочитаете все это.

Socket.Receive определяет перегрузку, которая позволяет вам указать, сколько байтов вы хотите получить. (Однако вы не гарантированно получите такое количество, поэтому вам все равно придется проверить возвращаемое значение.)

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