Асинхронные сокеты C # не возвращают всю страницу - PullRequest
1 голос
/ 03 августа 2011

Это моя часть создания сокета:

_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_client.BeginConnect(_IPEnd, new AsyncCallback(ConnectCallback), _client);
connectDone.WaitOne();
Send(_client, "GET / HTTP/1.1\r\nHost: www.google.de\r\nConnection: Keep-Alive\r\n\r\n");

Часть recv:

private void Receive()
    {
        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = _client;

        // Begin receiving the data from the remote device.
        _client.BeginReceive(state.buffer, 0, state.buffer.Length , 0, new AsyncCallback(ReceiveCallback), state);
    }

private void ReceiveCallback(IAsyncResult ar)
    {
        // Retrieve the state object and the client socket 
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket client = state.workSocket;

        // Read data from the remote device.
        int bytesRead = client.EndReceive(ar);

        if (bytesRead > 0)
        {
            // There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

            client.BeginReceive(state.buffer,0,state.buffer.Length, 0, new AsyncCallback(ReceiveCallback), state);
        }
        else 
        {
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead)); 
            int length = state.sb.ToString().Length;
            ProcessData(state.sb.ToString());

            receiveDone.Set();
        }

    }

Буфер

    public class StateObject
    {
        private Guid ID = Guid.NewGuid();
        // Client socket.
        public Socket workSocket = null;
        // Size of receive buffer.
        public const int BufferSize = 4096;
        // Receive buffer.
        public byte[] buffer = new byte[BufferSize];

        public StringBuilder sb = new StringBuilder();
    }

Почему этот код не возвращаетПолная страница?

Что-то не так с этой частью в recvcallback

if (bytesRead > 0)

Ответы [ 2 ]

2 голосов
/ 03 августа 2011

Вы, кажется, , предполагая , что вам перезвонят только тогда, когда или буфер заполнен или соединение было закрыто.Это просто не тот случай.Вы можете иметь буфер 8 КБ и 20 КБ данных, отправляемых с сервера, которые считываются как 2 КБ при каждом из 10 вызовов.

Если вы хотите читать до тех пор, пока соединение не будет закрыто, вы должны продолжать работать доclient.EndReceive возвращает 0. (Для HTTP с keepalive вам необходимо прочитать длину содержимого и продолжать, пока вы не прочитаете столько данных в теле.)

РЕДАКТИРОВАТЬ: я только что виделВы установили Keep-Alive на соединение.Не делайте этого, если вы хотите, чтобы сервер закрыл соединение и сообщал вам, что оно завершено!

(В общем, для всего этого, конечно, лучше использовать библиотеку HTTP - почему вы пишетеваш собственный код обработки HTTP?)

0 голосов
/ 03 августа 2011

Проверьте длину буфера.Вероятно, намного короче, чем эффективная длина страницы.Таким образом, вы должны накапливать порции, полученные в другом буфере, затем повторно запускать BeginReceive до тех пор, пока длина данных не станет равной нулю.

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