0

我想使用原始 C# 套接字执行以下操作。我知道通常最合适的方式是通过 HTTP 和 HTTP 客户端。浏览器知道这个连接必须以某种方式保持打开状态。

http://server.domain.com/protocol/do_something.txt

我正在 C# 中尝试以下操作,但没有运气。我究竟做错了什么?是否缺少标题?我应该以某种方式对发送到服务器的内容进行编码吗?对于 ReceiverSocket 客户端,我使用以下代码,但它只是一个非常标准的异步套接字客户端:https ://stackoverflow.com/a/10390066/971580

ReceiverSocket socket = new ReceiverSocket("server.domain.com", 80);
socket.Connect();
System.Threading.Thread.Sleep(1000);            
String message = "GET /protocol/do_something.txt HTTP/1.1";
message += "\r\n";
message += "\r\n";
socket.Send(message);

套接字可以成功连接,但是当我向服务器发送任何内容时,我没有得到任何响应。这就是我连接、发送和接收的方式。t (道歉:我试图在片段中这样做,而不是包括所有方法,但它看起来很可怕......)

    public ReceiverSocket(String address, int port) : base(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    {
        messageQueue = new Queue<MessageBase>();
        IPHostEntry ipHostInfo = Dns.GetHostEntry(address);
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        remoteEP = new IPEndPoint(ipAddress, port);
    }

    public void Connect()
    {
        this.BeginConnect(remoteEP, ConnectCallback, this);
    }

    private void ConnectCallback(IAsyncResult ar)
    {
        try
        {
            Socket client = (Socket)ar.AsyncState;
            if (client.Connected)
            {
                client.EndConnect(ar);
                Console.WriteLine("Connect Callback - Connected");
                StateObject state = new StateObject();
                state.workSocket = client;
                state.BufferSize = 8192;
                if (SocketConnected != null)
                    SocketConnected(client);

                client.BeginReceive(state.Buffer, state.readOffset, state.BufferSize - state.readOffset, 0, ReceiveCallback, state);
            }
            else
            {
                Thread.Sleep(5000);
                Connect();
            }
        }
        catch (Exception ex)
        {
            Reconnect();
        }
    }

    private void ReceiveCallback(IAsyncResult ar)
    {
        Console.WriteLine("Never gets here. . . ");
        try
        {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;
            if (client.Connected)
            {
                int bytesRead = client.EndReceive(ar);
                foreach (MessageBase msg in MessageBase.Receive(client, bytesRead, state))
                {
                    // Add objects to the message queue
                    lock (this.messageQueue)
                        this.messageQueue.Enqueue(msg);
                }


                if (DataRecieved != null)
                    DataRecieved(client, null);

                client.BeginReceive(state.Buffer, state.readOffset, state.BufferSize - state.readOffset, 0, ReceiveCallback, state);
            }
            else
            {
                Reconnect();
            }
        }
        catch (SocketException)
        {
            Reconnect();
        }
    }

    public void Send(String msg)
    {
        try
        {
            byte[] bytes = GetBytes(msg);

            if (this.Connected)
            {

                Console.WriteLine("Sending: " + msg);
                this.BeginSend(bytes, 0, bytes.Length, 0, SendCallback, this);
            }
            else
            {
                Reconnect();
            }
        }
        catch (SocketException sox)
        {
            Reconnect();
        }
        catch (Exception ex)
        {
            int i = 0;
        }
    }


    static byte[] GetBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }
    }

    public class StateObject
    {
        public Socket workSocket = null;
        public int readOffset = 0;
        public StringBuilder sb = new StringBuilder();

        private int bufferSize = 0;
        public int BufferSize
        {
            set
            {
                this.bufferSize = value;
                buffer = new byte[this.bufferSize];
            }

            get { return this.bufferSize; }
        }

        private byte[] buffer = null;
        public byte[] Buffer
        {
            get { return this.buffer; }
        }
    }

我没有包含message += "Connection: close"标头的事实不应该意味着套接字应该开始异步发送它拥有的任何数据吗?还要注意:我可以使用 Telnet 成功连接并发送数据,只是还没有使用套接字!

任何指针都将不胜感激。

谢谢。

4

1 回答 1

0

不要调用Send(),直到ConnectCallback()第一次调用,否则您可能会过早发送数据。使用Sleep()等待连接是错误的。

在完成发送数据BeginReceive()之前不要打电话。Send()

因为您使用的是 HTTP 1.1,所以是的,如果您连接到 HTTP 1.1 服务器,则默认情况下连接保持活动状态。服务器的Connection响应标头将指示服务器是否实际上保持连接打开。

此外,正如其他人所说,HTTP 1.1 请求必须具有Host标头,否则请求格式不正确并且可能被服务器拒绝/忽略。HTTP 1.1 有一个虚拟主机在同一个 IP 上运行的概念,因此Host标头告诉服务器客户端要与哪个主机通信。

于 2012-09-16T16:06:22.767 回答