1

こんにちは、Shoutcast ストリーム サイトに http 要求を送信して応答を読み込もうとしました。この 2 つのソースは 1 つはメイン (私は wpf でテスト済み) で、もう 1 つはソケットの小さなヘルパーです...まあlocalhost や他のサイトではすべて動作しますが、「209.9.238.6:6042」にリクエストを送信しようとすると、応答のヘッダーが完全ではなく切り捨てられます。

私は多くのテストを行いましたが、Thread.sleep(200); でのみ機能するものは何もありません。send と receive の間で (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();
            }
        }



    }
}
4

1 に答える 1

2

1回の読み取りで応答全体を取得できると想定しているようです。それは正しくありません。データが利用可能になると、ソケットからデータを取得します。アプリケーション レベルのプロトコル (HTTP や ICY など、使用しているプロトコル) に従って、さらにデータが来るかどうかを検出する必要があります。

現在、ソケット受信バッファにあるものは何でも消費しています。タイムアウト後にさらにデータが積み重なったという理由だけで待機が機能しているように見えますが、すべてを取得できるという保証はありません。

于 2013-05-24T07:19:17.333 に答える