POST-запрос с использованием сокетов C # - PullRequest
5 голосов
/ 18 февраля 2011

Я пытаюсь сделать аукционный снайпер для сайта. Чтобы сделать ставку, вам нужно отправить 4 параметра (и, конечно, куки) в / auction / place_bid. Мне нужно использовать сокеты, а не HttpWebRequest. Вот код:

        string request1 = "POST /auction/place_bid HTTP/1.1\r\nHost: *host here*\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)\r\nAccept: /*\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\nX-Requested-With: XMLHttpRequest\r\n" + cookies +"\r\n";
        string request3 = "token=" + token + "&aid=" + aid + "&bidReq=" + ptzReq + "&recaptcha_challenge_field=" + rcf + "&recaptcha_response_field=" + rrf+"\r\n\r\n";
        string request2 = "Content-Length: " + (Encoding.UTF8.GetByteCount(request1+request3)+23).ToString() + "\r\n";
        byte[] dataSent = Encoding.UTF8.GetBytes(request1+request2+request3);
        byte[] dataReceived = new byte[10000];
        Socket socket = ConnectSocket(server, 80);
        if (socket == null)
        {
            return null;
        }
        socket.Send(dataSent, dataSent.Length, 0);
        int bytes = 0;
        string page = "";
        do
        {
            bytes = socket.Receive(dataReceived, dataReceived.Length, 0);
            page = page + Encoding.ASCII.GetString(dataReceived, 0, bytes);
        }
        while (bytes > 0);

        return page;

Когда я пытаюсь получить веб-страницу, Visual Studio говорит, что «Операция на разблокированном сокете не может быть завершена немедленно», когда я добавляю

socket.Blocking = true;

Мое приложение перестает отвечать на запросы и через ~ 1 минуту возвращает страницу, но оно пустое! Когда я пытаюсь сделать запрос GET, он работает отлично. Я надеюсь, что вы мне поможете. Кстати, это первый раз, когда я использую сокеты, поэтому мой код довольно плохой, извините за это.

* Я использую класс ConnectSocket, который был приведен в качестве примера на msdn (ссылка ведет на русский MSDN, извините, я не нашел ту же статью на английском языке, но вы поймешь код все равно)

Ответы [ 2 ]

3 голосов
/ 18 февраля 2011

Как уже отмечали люди: HttpWebRequest не является причиной проблем с производительностью.Переключение на реализацию сокета ни на что не повлияет.

Дело в том, что HttpWebRequest может делать миллионы глупостей, если захочет, и все равно будет быстрее, чем время, необходимое для получения информации с веб-сервера.

Переключениереализация сокетов может ускорить процесс, если вы хорошо разбираетесь в сокетах и ​​протоколе http.У вас явно этого нет, поэтому я бы рекомендовал вам снова вернуться к HttpWebRequest.

Возможно, вы захотите использовать WebClient, если вы собираетесь получать множество страниц с одного и того же веб-сервера, так как онбудет поддерживать соединение.

Обновление

Мне не нужно много соединений, мне нужно сделать 1 запрос за раз, и это должно быть как можно быстрее

Хорошо.Тогда не имеет значения, какую реализацию вы используете.Задержка сети ВСЕГДА будет намного больше, чем фактическая реализация HTTP-клиента.Создание HTTP-запроса не требует больших ресурсов, синтаксический анализ ответа также не делает этого.

3 голосов
/ 18 февраля 2011

Заголовок Content-Length должен указывать размер содержимого.Вы устанавливаете его на общий размер ваших заголовков и содержимого.

Encoding.UTF8.GetByteCount(request1+request3)+23).ToString()

Поскольку контентная часть вашего сообщения просто request3,сервер терпеливо ждет ByteCount(request1)+23 больше байтов контента, который вы никогда не отправляете.

Попробуйте вместо этого:

"Content-Length: " + Encoding.UTF8.GetByteCount(request3).ToString() + "\r\n"

Другая проблема выглядит как ваш цикл:

do
{
    bytes = socket.Receive(dataReceived, dataReceived.Length, 0);
    page = page + Encoding.ASCII.GetString(dataReceived, 0, bytes);
}
while (bytes > 0);

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

Вы должны по крайней мере изменить его на while (bytes <= 0), что даст вам по крайней меренекоторые данные (вероятно, только стоимость первого пакета или около того).В идеале, вы должны продолжать вызывать Receive(), пока не увидите заголовок Content-Length в ответе, затем продолжайте вызывать Receive() до конца заголовков, затем прочитайте Content-Length больше байтов.

Поскольку выВы используете сокеты, вам действительно нужно заново реализовать протокол HTTP.

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