记一次网络请求异常:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

场景:

       在winform窗体里进行post请求,服务端是python-django写的。

现象:

       可以进行网络请求并返回数据,但是在winform窗体关闭时服务端出现了异常:

Exception happened during processing of request from ('127.0.0.1', 63951)
Traceback (most recent call last):
  File "C:\Python\Python37\lib\socketserver.py", line 650, in process_request_thread
    self.finish_request(request, client_address)
  File "C:\Python\Python37\lib\socketserver.py", line 360, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Python\Python37\lib\socketserver.py", line 720, in __init__
    self.handle()
  File "C:\Python\Python37\lib\site-packages\django\core\servers\basehttp.py", line 171, in handle
    self.handle_one_request()
  File "C:\Python\Python37\lib\site-packages\django\core\servers\basehttp.py", line 179, in handle_one_request
    self.raw_requestline = self.rfile.readline(65537)
  File "C:\Python\Python37\lib\socket.py", line 589, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。

       C#网络请求的代码如下:

string Url = "http://localhost:8000/calc";

string jsonParam = "{\"color1\":\"#ccff66\",\"color2\":\"#ccff77\"}";

var request = (HttpWebRequest)WebRequest.Create(Url);
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";
var byteData = Encoding.UTF8.GetBytes(jsonParam);
var length = byteData.Length;
request.ContentLength = length;

var writer = request.GetRequestStream();
writer.Write(byteData, 0, length);
writer.Close();

var response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
var streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
var responseString = streamReader.ReadToEnd();

streamReader.Close();
responseStream.Close();

原因:

       从异常日志可以看出,异常是在读取数据的时候抛出的。

       导致“Connection reset”的原因是服务器端因为某种原因关闭了Connection,而客户端依然在读写数据,此时服务器会返回复位标志“RST”,“RST”标志表示我不再发送数据也不接收数据了,然后此时客户端就会提示“java.net.SocketException: Connection reset”。 

        另一个比较常见的异常是“Connection reset by peer”,它和“Connection reset”的区别在于:

  • 服务器返回了“RST”时,如果此时客户端正在从Socket套接字的输出流中读数据则会提示Connection reset”;
  • 服务器返回了“RST”时,如果此时客户端正在往Socket套接字的输入流中写数据则会提示“Connection reset by peer”。

 

分析:

        C#中用HttpWebRequest进行网络请求时默认是长连接,可以打印request.KeepAlive值确认。因此建立连接后,在关闭窗口时会向服务端进行挥手来关闭TCP连接。

        而django中进行网络请求默认是短连接,这就导致客户端向服务端挥手时,服务端已经关闭了连接,出现异常。这里不敢确认,后面有时间研究一下吧

 

解决:

        知道了原因就可以从以下方面来解决:

  • 异常后重试
  • 客户端和服务端统一使用TCP长链接
  • 客户端和服务端统一使用TCP短链接

       最终解决方法是在客户端请求时设置为短连接:

request.KeepAlive = false;

 

 

 

 

 

参考:https://blog.csdn.net/maligebazi/article/details/80304894

 

你可能感兴趣的:(网络)