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 に答える