ソケットと 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()
この投稿の上部にあるメソッドに渡します。