0

ソケットと NetworkStream を使用して非同期 TPL ファイル サーバーを作成しようとしています。テストすると、ブラウザの小さな HTML ファイル (1.9 KB) は問題なく送信され、リンク先の Javascript や CSS ファイルも送信されることがありますが、Flash、画像などを含む HTML ページからそれ以上はダウンロードされません。接続エラーを含め、エラーは発生しません。96K の画像をダウンロードできますが、それが限界です。Connection: Keep-Aliveすべての応答ヘッダーを設定しました。

出力ストリーミングが停止しているように見える理由を誰か知っていますか?

async Task<> WriteToStream(NetworkStream _networkStream, string filePath, int startingPoint = 0)
    {
    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Open, FileAccess.Read, FileShare.Read,
        bufferSize: 4096, useAsync: true))
        {
        byte[] buffer = new byte[4096];
        int numRead;
        while ((numRead = await sourceStream.ReadAsync(buffer, 0, buffer.Length)) != 0)
        {             
             _networkStream.Write(buffer, 0, numRead);
        }
    }
}

私もこれを置き換えてみました:

_networkStream.Write(buffer, 0, numRead);

これとともに:

await _networkStream.WriteAsync(buffer, 0, numRead);

私はまだ同じ問題を抱えています。

着信UDPおよびTCPリクエストにアクセスする必要があるため、HttpListenerまたはTcpListenerクラスを使用できないため、ソケットを使用しています。

WriteToStream()この簡略化されたメソッドで呼び出すことができます:

private async void SendFileExample()
{
    //This method is only for demonstration, so parameters are hardcoded.

    // Get info and assemble header
    string file = @"C:\www\webpage.html";
    byte[] data = null;
    string responseCode = "200 OK";
    string contentType = "text/html";
    long dataLength = 1901;
    string serverName = "my Stack Overflow server is overflowing with...";

    string header = string.Format("HTTP/1.1 {0}\r\n"
        + "Server: {1}\r\n"
        + "Content-Length: {2}\r\n"
        + "Content-Type: {3}\r\n"
        + "Connection: Keep-Alive\r\n"
        + "\r\n",
        responseCode, serverName, dataLength, contentType);

    var headerBytes = Encoding.ASCII.GetBytes(header);

    //send header
    await _networkStream.WriteAsync(headerBytes, 0, headerBytes.Length);

    //send payload
    await WriteToStream(_networkStream, file, 0);

    //flush networkstream
    await _networkStream.FlushAsync();             
}

編集:

ここでリッスン ループを呼び出します。

_listenTask = Task.Factory.StartNew(() => ListenLoop());

リクエストをスプールし、毎回クライアントを生成するループは次のとおりです。

private async void ListenLoop()
{
    for (; ; )
    {
        // Wait for connection
        var socket = await _tcpListener.AcceptSocketAsync();
        if (socket == null)
            break;

        // Got new connection, create a client handler for it
        var client = new Client(socket,dbInfo,frmClient);
        // Create a task to handle new connection
        Task.Factory.StartNew(client.Do);
    }
}

接続は次の方法で処理されます。

public async void Do()
{
    byte[] buffer = new byte[4096];
    for (; ; )
    {
        // Read a chunk of data
        int bytesRead = await _networkStream.ReadAsync(buffer, 0, buffer.Length);

        // If Read returns with no data then the connection is closed.
        if (bytesRead == 0)
            return;

        // Write to buffer and process request
        _memoryStream.Seek(0, SeekOrigin.End);
        _memoryStream.Write(buffer, 0, bytesRead);
        bool done = ProcessHeader();
        if (done)
            break;
    }

}

ProcessHeader()ほとんどの場合、MIME タイプなどのメタデータを取得し、ストリームをWriteToStream()この投稿の上部にあるメソッドに渡します。

4

0 に答える 0