[分享]一个封锁操作被对 WSACancelBlockingCall 的调用中断 ErrorCode=10004
在读取网络流之前,先添加一条判断语句:
//client.Available属性进行判断,当Available属性大于0时才开始从缓冲区读取网络数据 if (client.Available <= 0) continue;
MSDN对Available的解释是:
“Available 属性用于确定在网络缓冲区中排队等待读取的数据的量。 如果数据可用,可调用 Read 获取数据。 如果无数据可用,则 Available 属性返回 0。
如果远程主机处于关机状态或关闭了连接,则 Available 属性将引发SocketException。如果远程主机处于关机状态或关闭了连接,则 Available 属性将引发SocketException”。
也就是说,错误的原因在于,但调用Close后,线程恰好继续向网络缓冲区中读取数据,所以引发SocketException。
今天搜索度娘一下午都没找到答案,最终找到了http://www.cnblogs.com/xiwang/archive/2012/10/25/2740114.html得到了启发
但我的代码是引发了IOException异常
另附接收网络流部分完整代码:
/// <summary> /// 接收服务器发送的信息 /// </summary> private void ReceiveData() { while (isDisconnect == false) { //保存接收的命令字符串 string receiveString = null; //解析命令用 //每条命令均带有一个参数,值为true或false,表示是否有紧跟的字节数组 string[] splitString = null; byte[] receiveBytes = null; try { //client.Available属性进行判断,当Available属性大于0时才开始从缓冲区读取网络数据 if (client.Available <= 0) continue; //从网络流中读出命令字符串 //此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串 receiveString = br.ReadString(); splitString = receiveString.Split('|'); if (splitString[1] == "true") { //先从网络流中读出32位的长度前缀 int bytesLength = br.ReadInt32(); //然后读出指定长度的内容保存到字节数组中 receiveBytes = br.ReadBytes(bytesLength); } } catch (Exception ex) { //底层套接字不存在时会出现异常,将错误信息写入Log new ExLog().WriteLog("ReceiveData", ex.Message); } if (receiveString == null) { if (isDisconnect == false) { //如果与服务器断开代码Application.Exit(); MessageBox.Show("与服务器的连接中断。\n\n请检查网络,并重新开启本程序。", "系统错误", MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning); } break; } //getMessage("收到命令:" + receiveString); //if (receiveBytes != null) //{ // getMessage(string.Format("收到加密内容:{0}", Encoding.Default.GetString(receiveBytes))); //} } //Application.Exit(); }
浙公网安备 33010602011771号