有时我得到以下错误,当我做HttpWebRequest到一个WebService。我也复制了下面的代码。
System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:80
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetRequestStream()
ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.PreAuthenticate = true;
request.Credentials = networkCredential(sla);
request.Method = WebRequestMethods.Http.Post;
request.ContentType = "application/x-www-form-urlencoded";
request.Timeout = v_Timeout * 1000;
if (url.IndexOf("asmx") > 0 && parStartIndex > 0)
{
AppHelper.Logger.Append("#############" + sla.ServiceName);
using (StreamWriter reqWriter = new StreamWriter(request.GetRequestStream()))
{
while (true)
{
int index01 = parList.Length;
int index02 = parList.IndexOf("=");
if (parList.IndexOf("&") > 0)
index01 = parList.IndexOf("&");
string parName = parList.Substring(0, index02);
string parValue = parList.Substring(index02 + 1, index01 - index02 - 1);
reqWriter.Write("{0}={1}", HttpUtility.UrlEncode(parName), HttpUtility.UrlEncode(parValue));
if (index01 == parList.Length)
break;
reqWriter.Write("&");
parList = parList.Substring(index01 + 1);
}
}
}
else
{
request.ContentLength = 0;
}
response = (HttpWebResponse)request.GetResponse();
如果总是发生这种情况,这实际上意味着机器存在,但它没有在指定端口上侦听服务,或者有防火墙阻止您。
如果这种情况偶尔发生(您使用了“有时”这个词),并且重试成功,则很可能是因为服务器有完整的“积压”。
当您等待侦听套接字接受时,您将处于积压中。这个积压是有限的,而且相当短——1、2或3的值并不罕见——因此操作系统可能无法将您的请求排队以接受消费。
backlog是listen函数上的一个参数——在这方面,所有语言和平台基本上都有相同的API,甚至c#也是如此。如果您控制服务器,则此参数通常是可配置的,并且可能从某些设置文件或注册表中读取。研究如何配置服务器。
如果您编写的是服务器,那么在套接字的accept中可能会有大量的处理,最好将其转移到单独的工作线程,以便您的accept始终准备好接收连接。您可以选择不同的体系结构来减少客户端排队和顺序处理。
不管您是否可以增加服务器的积压,您都需要在客户端代码中重试逻辑来处理这个问题——因为即使有很长的积压,服务器也可能在同一时间在该端口上接收大量其他请求。
当NAT路由器的映射端口耗尽时,很少会出现这种错误。不过,我认为我们可以放弃这种可能性,因为在耗尽之前,路由器有64K个同时连接到同一个目的地地址/端口。
我想分享我发现的这个答案,因为问题的原因不是防火墙或进程没有正确侦听,而是我使用的微软提供的代码示例。
https://msdn.microsoft.com/en-us/library/system.net.sockets.socket%28v=vs.110%29.aspx
我几乎完全按照所写的那样实现了这个函数,但发生的事情是我得到了这个错误:
2016-01-05 12:00:48075 [10] ERROR -错误是:System.Net.Sockets.SocketException (0x80004005): No connection could be made because The target machine actively refused it [fe80::caa:745:a1da:e6f1%11]:4080
这段代码将表示套接字已连接,但不是在正确通信实际所需的正确IP地址下。(微软提供)
private static Socket ConnectSocket(string server, int port)
{
Socket s = null;
IPHostEntry hostEntry = null;
// Get host related information.
hostEntry = Dns.GetHostEntry(server);
// Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
// an exception that occurs when the host IP Address is not compatible with the address family
// (typical in the IPv6 case).
foreach(IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipe = new IPEndPoint(address, port);
Socket tempSocket =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
tempSocket.Connect(ipe);
if(tempSocket.Connected)
{
s = tempSocket;
break;
}
else
{
continue;
}
}
return s;
}
我重写了代码,只使用它找到的第一个有效IP。我只关心使用IPV4,但它与localhost, 127.0.0.1,和您的网卡的实际IP地址,其中微软提供的例子失败了!
private Socket ConnectSocket(string server, int port)
{
Socket s = null;
try
{
// Get host related information.
IPAddress[] ips;
ips = Dns.GetHostAddresses(server);
Socket tempSocket = null;
IPEndPoint ipe = null;
ipe = new IPEndPoint((IPAddress)ips.GetValue(0), port);
tempSocket = new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Platform.Log(LogLevel.Info, "Attempting socket connection to " + ips.GetValue(0).ToString() + " on port " + port.ToString());
tempSocket.Connect(ipe);
if (tempSocket.Connected)
{
s = tempSocket;
s.SendTimeout = Coordinate.HL7SendTimeout;
s.ReceiveTimeout = Coordinate.HL7ReceiveTimeout;
}
else
{
return null;
}
return s;
}
catch (Exception e)
{
Platform.Log(LogLevel.Error, "Error creating socket connection to " + server + " on port " + port.ToString());
Platform.Log(LogLevel.Error, "The error is: " + e.ToString());
if (g_NoOutputForThreading == false)
rtbResponse.AppendText("Error creating socket connection to " + server + " on port " + port.ToString());
return null;
}
}
通常,连接脚本不会提到要使用的端口。例如:
$mysqli = mysqli_connect('127.0.0.0.1', 'user', 'password', 'database');
所以,要连接到一个不使用端口3306的管理器,你必须在连接请求上指定端口号:
$mysqli = mysqli_connect('127.0.0.0.1', 'user', 'password', 'database', '3307');
要检查MySQL或MariaDB数据库管理器上的连接,使用脚本:
里面(64)\ www \ testmysql.php
在浏览器地址栏中输入“http://localhost/testmysql.php”,然后根据参数修改脚本。