0

こんにちは。私の英語自体がウクライナ出身であることをお詫びし、下手に話します)) 次の問題があります。私のプログラムは異なる URL でリクエストを作成し、回答からいくつかの情報を解析します。URL数は数百万以上。迅速に処理するために、多くのスレッドを使用します。時には 500 ~ 700 スレッド程度です。一部のマシンではプログラムが正常に動作していますが、エラーが発生するマシンがあります。次のようなエラー:System.Net.Sockets.SocketException (0x80004005): The remote host forcibly broke the existing connection.

私のコード:

void _thread()
{
while(true)
{
string request =
"POST http://" + hostf + "/ HTTP/1.1\r\n" +
"Host: " + host +
"\r\nConnection: Close\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
"Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\n" +
"Content-Length: " + ByteArr.Length +
"\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n\r\n" +
parametres;

Byte[] bytesSent = Encoding.GetEncoding("UTF-8").GetBytes(request);
Byte[] bytesReceived = new Byte[256];
Socket s = null;
IPHostEntry hostEntry = null;
hostEntry = Dns.GetHostEntry(host);
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, 80);
Socket tempSocket =new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tempSocket.Connect(ipe);
if (tempSocket.Connected)
{
s = tempSocket;
break;
}
else
{
continue;
}
}
if (s == null)
continue;
s.Send(bytesSent, bytesSent.Length, 0);
int bytes = 0;
string page = "";
do
{
bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
page = page + Encoding.GetEncoding("UTF-8").GetString(bytesReceived, 0, bytes);
}
while (bytes > 0);
s.Shutdown(SocketShutdown.Both);
s.Close();
//here some work whith page content
}
}

ご覧のとおり、各スレッドはソケットを作成し、リクエストを送信し、応答を取得してソケットを閉じます。各スレッドは独自のソケットを開き、異なる URL で動作しますが、一部のマシンでは、スレッドの数が特定の数を超えるとエラーが発生し、すべてのソケットが正常に動作しません。なぜそれが起こるのですか?一部のマシンでは、接続に何らかの制限がありますか? よろしくお願いします。

4

1 に答える 1

0

シャットダウンしないでください(両方)。続いてクローズ。s.shutdown() を削除し、s.Close() を残してから試してください。両方ともシャットダウンするとソケット記述子が使用可能になるため、次のクローズでは、所有していたソケットの代わりに他のソケットをクローズできることを覚えていると思います。

編集: いくつかのコードの変更:

受信バッファを少し増やします

bytes[] bytesReceived = new bytes[1024];

また、リクエスト文字列を送信するときに、受信者に完了を伝えます。

s.Send(bytesSent, bytesSent.Length, 0);
// Tell the receiver we are done sending data
s.Shutdown(SocketShutdown.Send);

また、ソケットの読み取り時にエラーをチェックし、String の代わりに StringBuilder を使用する必要があります (String にテキストを追加するよりも多少高速です)。

StringBuilder page = new StringBuilder();
do
{
    bytes = s.Receive(bytesReceived, bytesReceived.Length, 0);
    if (bytes == -1)
    {
         // Error in socket, quit
         s.Close();
         return;
    }
    else if (bytes > 0)
         page.Append(Encoding.GetEncoding("UTF-8").GetString(bytesReceived, 0, bytes));
}
while (bytes > 0);

最後に、ソケットを閉じます。

// s.ShutDown(Socketshutdown.Both);
s.close();

この変更を試してみて、解決されるかどうかを確認してください。

于 2013-07-27T18:56:29.750 に答える