Я написал свой собственный HTTP-сервер для встраивания в настольное приложение, и он работает (запускает сервер на локальном хосте), за исключением того, что я получаю странный запрос на сокет, который вызывает закрытие соединения, так что новых запросы обрабатываются. Запрос происходит примерно через 15 секунд после открытия веб-страницы. Насколько я понимаю, пакет содержит длинную серию \0\0\0\0\0\0\0\0\0\0\0\0....... Я понятия не имею, что вызывает это, и как с этим справиться. В течение этих первых 15 секунд я могу делать все, что мне нужно, но как только это произойдет, новые запросы будут невозможны, и сервер не будет отвечать ни на какие новые запросы. Это также не происходит каждый раз, когда я запускаю приложение, но я не могу понять, почему.

while (true)
{
    //Accept a new connection
    Socket mySocket = _listener.AcceptSocket();
    if (mySocket.Connected)
    {
        Byte[] bReceive = new Byte[1024];
        int i = mySocket.Receive(bReceive, bReceive.Length, 0);
        string sBuffer = Encoding.ASCII.GetString(bReceive); 
        if (sBuffer.Substring(0, 3) != "GET")
        {
            Console.WriteLine(sBuffer);
            mySocket.Close();
            return;
        }    
        ........handle valid requests
    }    
}
-2
jugg1es 13 Авг 2014 в 21:14
4
have no idea what's causing this. Потому что вы не используете i, возвращаемый из Receive при использовании Encoding.ASCII.GetString. Вы просто предполагаете, что прочитали bReceive.Length байт ....
 – 
L.B
13 Авг 2014 в 21:19
Классическая проблема «TCP основан на потоке». То, что вы получаете, может быть не всем сообщением, может не заполнять буфер и т. Д.
 – 
ziya
13 Авг 2014 в 21:21
@ L.B а, я понимаю, о чем вы говорите. Неосторожная ошибка, спасибо
 – 
jugg1es
13 Авг 2014 в 21:23
Эта длинная серия \0, которую вы получаете, вероятно, является результатом чтения менее 1024 байтов данных. то есть там всего 100 байт данных, поэтому у вас будет 924 экземпляра /0.
 – 
Joshua Shearer
13 Авг 2014 в 21:24

1 ответ

Лучший ответ

Попробуйте что-то вроде этого:

while (true)
{
    //Accept a new connection
    Socket mySocket = _listener.AcceptSocket();
    if (mySocket.Connected)
    {
        Byte[] bReceive = new Byte[1024];
        int i = mySocket.Receive(bReceive, bReceive.Length, 0);
        if(i > 0) // added check to make sure data is received
        {
            string sBuffer = Encoding.ASCII.GetString(bReceive, 0, i); // added index and count
            if (sBuffer.Substring(0, 3) != "GET")
            {
                Console.WriteLine(sBuffer);
                mySocket.Close();
                return;
            }    
            ........handle valid requests
        }
    }    
}

В конечном итоге - вам нужно будет что-то сделать, если i == 1024 - потому что в этом случае данных больше, чем вы читаете в mySocket.Receive.

В качестве примечания - я могу изменить if (sBuffer.Substring(0, 3) != "GET") к if (sBuffer.StartsWith("GET"))

Его немного легче читать, и он имеет дополнительное преимущество, так как не требует изменения длины подстроки, если (по какой-то нечетной причине) GET изменился на что-то другое.

Изменить - это позволит многократно вызывать mySocket.Receive, когда встречается больше данных, чем 1024 байта:

        while (true)
        {
            //Accept a new connection
            Socket mySocket = _listener.AcceptSocket();
            if (mySocket.Connected)
            {
                StringBuilder sb = new StringBuilder();
                Byte[] bReceive = new Byte[1024];
                int i;
                while ((i = mySocket.Receive(bReceive, bReceive.Length, 0) > 0))
                {
                    sb.Append(Encoding.ASCII.GetString(bReceive, 0, i)); // added index and count
                }
                string sBuffer = sb.ToString();
                if (sBuffer.Substring(0, 3) != "GET")
                {
                    Console.WriteLine(sBuffer);
                    mySocket.Close();
                    return;
                }
            }
        }
0
Mike 13 Авг 2014 в 21:40
Майк, извини, недостаточно хорош. 1) mySocket.Receive никогда не вернет значение <= 0, пока соединение не будет закрыто (поэтому интерактивный протокол невозможен) 2) Вторая часть моего первого комментария. Что, если байты [95,150] разделены (отправлены двумя разными пакетами) для char 'Ö' в длинной строке.
 – 
L.B
13 Авг 2014 в 21:48
1
Кстати: Кто удалил предыдущие комментарии и почему?
 – 
L.B
13 Авг 2014 в 21:50
Не я. Наверное, это был мод.
 – 
Mike
13 Авг 2014 в 22:02
Я все еще на краю своего места жду вашего серебряного ответа, а не просто комментариев.
 – 
Mike
13 Авг 2014 в 22:03
Майк, ваш ответ уже принят . Так что не нужно тратить время впустую ... Просто подсказка: new StreamReader(tcpClient.GetStream()). Его метод ReadLine может решить все эти проблемы :)
 – 
L.B
13 Авг 2014 в 22:06