1

嗨,我尝试向 Shoutcast 流站点发送和 http 请求,然后读取响应,我有这两个来源,一个是主要来源(我已经用 wpf 测试过),另一个是套接字的小帮手......好吧一切正常,本地主机和其他站点但是当我尝试向“209.9.238.6:6042”发送请求时,响应的标头永远不会完成,而是被截断。

我做了很多测试,但它只适用于 Thread.sleep(200); 在发送和接收之间看(1),所以看起来listen()来得太早了,只下载了一部分......

你能帮助我吗?

主文件

 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;
        }

    }


}

助手.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

您似乎认为您将在一次阅读中获得全部回复。这是不正确的。当数据可用时,您将从套接字获取一些数据。您需要根据应用程序级协议检测是否有更多数据 - HTTP 或 ICY 或您正在使用的任何内容,如果是,则重新武装异步读取。

现在,您正在消耗套接字接收缓冲区中发生的任何内容。等待似乎只是因为在超时之后有更多的数据堆积在那里,但不能保证你得到了一切。

于 2013-05-24T07:19:17.333 回答