套接字错误当线程数超过某个级别时发生流动

本文关键字:错误 线程 套接字 | 更新日期: 2023-09-27 18:25:07

下午好。我为我来自乌克兰的英语道歉,说得很糟糕))我有以下问题,我的程序在不同的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,但在某些机器上,当线程数超过某个数时,错误就会开始,所有套接字都无法正常工作。有人能帮我提些建议吗?为什么会这样?有些机器对连接有某种限制,或者什么?提前谢谢大家。

套接字错误当线程数超过某个级别时发生流动

不要关闭(两者都关闭);然后是一个结束。删除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);

您还必须在读取套接字时检查错误,并使用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();

您可以尝试进行此修改,看看它是否已解决。