Неполный заголовок с сокетом C#

Привет, я пытаюсь отправить HTTP-запрос на сайт потока Shoutcast, а затем прочитать ответ, у меня есть два источника, один из которых является основным (я тестировал с wpf), а другой - маленький помощник для сокетов... хорошо все работает, с localhost и другим сайтом, но когда я пытаюсь отправить запрос на "209.9.238.6:6042", заголовок в ответе никогда не завершается, а пересекается.

Я сделал много тестов, но ничего не работает, только с Thread.sleep(200); между посылкой и приемом посмотрите на (1), поэтому кажется, что listen() приходит слишком рано и загружается только часть...

вы не могли бы мне помочь?

main.cs

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void connectionButton_Click(object sender, RoutedEventArgs e)
        {
            var url = "209.9.238.6:6042";

            var sockHelp = new SocketHelper(url);

            sockHelp.onConnect += sockHelp_onConnect;
            sockHelp.connect();

        }

        void testDebug(string str) {

            Action action = () => debugTxt.Text = str;
            Dispatcher.BeginInvoke(action);

        }

        void sockHelp_onConnect(object sender, SocketHelperEventArgs e)
        {

            var sockHelp = sender as SocketHelper;

            testDebug("Connected");

            var header = "";
            header+="GET / HTTP/1.0\r\n";
            header+="Accept: */*\r\n";
            header+="Host: 209.9.238.6\r\n";
            header+="Connection: close\r\n\r\n";

            sockHelp.onSend += sockHelp_onSend;
            sockHelp.sendAsync(Encoding.UTF8.GetBytes(header));

        }

        private void sockHelp_onSend(object sender, SocketAsyncEventArgs e)
        {
            var sockHelp = sender as SocketHelper;
            sockHelp.onReceive+=sockHelp_onReceive;

        //Thread.Sleep(200); (1)  uncomment this line... to make works

            sockHelp.listen();
        }

        void sockHelp_onReceive(object sender, SocketAsyncEventArgs arg_)
        {
            testDebug("Receiving");


            var t = Encoding.UTF8.GetString(arg_.Buffer);
            var idx = IndexOf(arg_.Buffer, new byte[] { 0x0d, 0x0a, 0x0d, 0x0a });

            if (idx < 0)
            {
                testDebug(Encoding.UTF8.GetString(arg_.Buffer));
                return ;
            }
            byte[] binBuff = new byte[idx + 1]; 
            System.Buffer.BlockCopy(arg_.Buffer, 0, binBuff, 0, idx + 1);
            testDebug(Encoding.UTF8.GetString(binBuff));
        }

        private int IndexOf(byte[] searchIn, byte[] searchFor)
        {
            if ((searchIn != null) && (searchIn != null))
            {
                if (searchFor.Length > searchIn.Length) return 0;
                for (int i = 0; i < searchIn.Length; i++)
                {
                    int startIndex = i;
                    bool match = true;
                    for (int j = 0; j < searchFor.Length; j++)
                    {
                        if (searchIn[startIndex] != searchFor[j])
                        {
                            match = false;
                            break;
                        }
                        else if (startIndex < searchIn.Length)
                        {
                            startIndex++;
                        }

                    }
                    if (match)
                        return startIndex - searchFor.Length;
                }
            }
            return -1;
        }

    }


}

helper.cs

namespace TestSocket
{
    /// <summary>

    /// </summary>
    public class SocketHelperEventArgs : EventArgs
    {

        public SocketHelperEventArgs(SocketError se)
        {
            socketError = se;
        }
        public SocketHelperEventArgs() { }
        SocketError socketError;
        SocketAsyncEventArgs args;
    }


    public class SocketHelper
    {
        byte[] _buffer = new byte[1024*2];
        SocketAsyncEventArgs _args = new SocketAsyncEventArgs();

        readonly Socket _socket;

        public event EventHandler<SocketHelperEventArgs> onError;
        public event EventHandler<SocketHelperEventArgs> onConnect;

        public event EventHandler<SocketAsyncEventArgs> onReceive;
        public event EventHandler<SocketAsyncEventArgs> onSend;

        public SocketHelper(string url)
        {

            int port=0;
            string[] addressVector = url.Split(':');
            if (addressVector.Length == 1)
                port = 80;
            else
                port = int.Parse(addressVector[1]);

            _args.RemoteEndPoint = new DnsEndPoint(addressVector[0], port); ;

            _args.Completed += SocketAsyncEventArgs_Completed;


            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


        }


        public void listen()
        {
            _args.SetBuffer(_buffer, 0, _buffer.Length);     

            _socket.ReceiveAsync(_args);
        }


        public void connect()
        {

            bool completesAsynchronously = _socket.ConnectAsync(_args);

            if (!completesAsynchronously)
            {
                SocketAsyncEventArgs_Completed(_args.ConnectSocket, _args);

            }
        }


        public void sendAsync(byte[] data) {

            _args.SetBuffer(data, 0, data.Length);
            _socket.SendAsync(_args);
        }

        private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
        {

            // check for errors 
            if (e.SocketError != SocketError.Success)
            {

                if (onError != null) onError(this, new SocketHelperEventArgs(e.SocketError));

                CleanUp(e);
                return;
            }

            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Connect:
                    if (onConnect != null) onConnect(this, EventArgs.Empty as SocketHelperEventArgs);
                    break;
                case SocketAsyncOperation.Send:
                    if (onSend!= null) onSend(this, e);
                    break;
                case SocketAsyncOperation.Receive:
                    if (onReceive != null) onReceive(this,e);
                    break;
            }
        }

        private void CleanUp(SocketAsyncEventArgs e)
        {
            if (e.ConnectSocket != null)
            {
                e.ConnectSocket.Shutdown(SocketShutdown.Both);
                e.ConnectSocket.Close();
            }
        }



    }
}

1 ответ

Решение

Вы, кажется, предполагаете, что получите полный ответ за одно чтение. Это не правильно. Вы получите некоторые данные из сокета, когда они будут доступны. Вам необходимо определить, есть ли еще данные, поступающие в соответствии с протоколом уровня приложения - HTTP или ICY или что вы используете, и, если это так, повторно включить асинхронное чтение.

Прямо сейчас вы потребляете все, что происходит в буфере приема сокета. Ожидание, кажется, работает только потому, что после этого таймаута накапливается больше данных, но нет никакой гарантии, что вы получите все.

Другие вопросы по тегам