16

HTTP requestソケットを使用して作成しようとしています。私のコードは次のとおりです。

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
class test
{
    public static void Main(String[] args)
    {
        string hostName = "127.0.0.1";
        int hostPort = 9887;
        int response = 0;

        IPAddress host = IPAddress.Parse(hostName);
        IPEndPoint hostep = new IPEndPoint(host, hostPort);
        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        sock.Connect(hostep);

        string request_url = "http://127.0.0.1/register?id=application/vnd-fullphat.test&title=My%20Test%20App";
        response = sock.Send(Encoding.UTF8.GetBytes(request_url));
        response = sock.Send(Encoding.UTF8.GetBytes("\r\n"));

        bytes = sock.Receive(bytesReceived, bytesReceived.Length, 0);
        page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
        Console.WriteLine(page);
        sock.Close();
    }
}

上記のコードを実行しても何も起こりませんが、request_urlブラウザーに入力すると、Snarl からその旨の通知が届き、Application Registeredブラウザーからの応答は次のようになります。

SNP/2.0/0/OK/556

私のコードから得られる応答はSNP/3.0/107/BadPacket.

それで、私のコードの何が問題なのですか。

Snarl リクエストのフォーマット仕様

4

4 に答える 4

16

私はSNPについて何も知りません。あなたのコードは、受信側で少し混乱しています。以下の例を使用して、HTTP GET 要求に対するサーバー応答を送信および読み取りました。最初にリクエストを見てから、レスポンスを調べてみましょう。

HTTP GET リクエスト:

GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive
Accept: text/html
User-Agent: CSharpTests

string - "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nAccept: text/html\r\nUser-Agent: CSharpTests\r\n\r\n"

サーバー HTTP 応答ヘッダー:

HTTP/1.1 200 OK
Date: Sun, 07 Jul 2013 17:13:10 GMT
Server: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16
Last-Modified: Sat, 30 Mar 2013 11:28:59 GMT
ETag: \"ca-4d922b19fd4c0\"
Accept-Ranges: bytes
Content-Length: 202
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html

string - "HTTP/1.1 200 OK\r\nDate: Sun, 07 Jul 2013 17:13:10 GMT\r\nServer: Apache/2.4.4 (Win32) OpenSSL/0.9.8y PHP/5.4.16\r\nLast-Modified: Sat, 30 Mar 2013 11:28:59 GMT\r\nETag: \"ca-4d922b19fd4c0\"\r\nAccept-Ranges: bytes\r\nContent-Length: 202\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"

応答ヘッダーの Content-Length で指定されているとおり、正確に 202 バイトであることが既にわかっているため、サーバー応答の本文を意図的に省略しました。

HTTP 仕様に目を通すと、HTTP ヘッダーが空の改行 ("\r\n\r\n") で終わっていることがわかります。したがって、それを検索するだけです。

実際のコードを見てみましょう。System.Net.Sockets.Socket 型の可変ソケットを想定します。

socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect("127.0.0.1", 80);
string GETrequest = "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: keep-alive\r\nAccept: text/html\r\nUser-Agent: CSharpTests\r\n\r\n";
socket.Send(Encoding.ASCII.GetBytes(GETrequest));

リクエストをサーバーに送信しました。レスポンスを受信して​​正しく解析しましょう。

bool flag = true; // just so we know we are still reading
string headerString = ""; // to store header information
int contentLength = 0; // the body length
byte[] bodyBuff = new byte[0]; // to later hold the body content
while (flag)
{
// read the header byte by byte, until \r\n\r\n
byte[] buffer = new byte[1];
socket.Receive(buffer, 0, 1, 0);
headerString += Encoding.ASCII.GetString(buffer);
if (headerString.Contains("\r\n\r\n"))
{
    // header is received, parsing content length
    // I use regular expressions, but any other method you can think of is ok
    Regex reg = new Regex("\\\r\nContent-Length: (.*?)\\\r\n");
    Match m = reg.Match(headerString);
    contentLength = int.Parse(m.Groups[1].ToString());
    flag = false;
    // read the body
    bodyBuff = new byte[contentLength];
    socket.Receive(bodyBuff, 0, contentLength, 0);
}
}
Console.WriteLine("Server Response :");
string body = Encoding.ASCII.GetString(bodyBuff);
Console.WriteLine(body);
socket.Close();

これはおそらく C# でこれを行うには最悪の方法です。.NET には HTTP 要求と応答を処理するためのクラスがたくさんありますが、それでも必要な場合は機能します。

于 2013-07-07T17:44:17.307 に答える
12

ヘッダーの終わりを示すために、最後にcontent-lengthと2つの改行を含める必要があります。

var request = "GET /register?id=application/vnd-fullphat.test&title=My%20Test%20App HTTP/1.1\r\n" + 
    "Host: 127.0.0.1\r\n" +
    "Content-Length: 0\r\n" +
    "\r\n";

HTTP 1.1仕様は、次の場所にあります:http ://www.w3.org/Protocols/rfc2616/rfc2616.html

于 2012-08-08T11:22:36.167 に答える
1

HTTP リクエストの最小要件は「GET / HTTP/1.0\r\n\r\n」です (ホストの削除が許可されている場合)。しかし、SNARL では、コンテンツの長さを入力する必要があります (私が最もよく耳にしたものです)。

そう、

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

        sck.Connect(ip, port);
        sck.Send(Encoding.UTF8.GetBytes("THE HTTP REQUEST HEADER"));
        Console.WriteLine("SENT");
        string message = null;
        byte[] bytesStored = new byte[sck.ReceiveBufferSize];
        int k1 = sck.Receive(bytesStored);
        for (int i = 0; i < k1; i++)
        {
            message = message + Convert.ToChar(bytesStored[i]).ToString();
        }
        Console.WriteLine(message); // PRINT THE RESPONSE

いくつかのサイトでテストしましたが、完全に機能します。うまくいかない場合は、ヘッダーを追加して修正する必要があります (最も可能性の高い解決策)。

于 2016-09-24T09:51:40.930 に答える
1

あなたの要求は正しくありません。ウィキペディアによると、HTTP Get リクエストは次のようになっている必要があります。

string request = "GET /register?id=application/vnd-fullphat.test&title=My%20Test%20App HTTP/1.1\r\nHost: 127.0.0.1\r\n";
于 2012-08-08T10:58:09.360 に答える