无法访问已释放的对象。 对象名:“System.Net.Sockets.Socket”。

gs0038 2016-11-22 08:11:55
无法访问已释放的对象。
对象名:“System.Net.Sockets.Socket”。 在 System.Net.Sockets.Socket.get_Available()

这是我的socket服务端发生的异常;
我的服务端socket是异步接收客户端数据,上面这段异常是在客户端连接服务端之后,不给服务端发送任何数据包的情况下
服务端检查到并关闭掉该客户端连接,试过先Shutdown(SocketShutdown.Both);然后再close();然而并没有用,


检查是一个定时器,每分钟检查一次,查检是一个for所有的客户端检查连接数据包情况;满足关闭条件则关闭客户端释放资源
,就是当我关闭客户端释放资源的时候,就发生错误哦就是close之后,readCallBack里面就发生这个异常了,我不知道要怎么做才能不让这个异常发生,希望知道的人能告诉我,在这里谢谢了
以下是接收回调函数

public virtual void ReadCallback(IAsyncResult ar)
{
try
{
string _content = string.Empty;
SocketClientVO _state = (SocketClientVO)ar.AsyncState;
Socket _handler = _state.m_socket;
int _Available = _handler.Available;
byte[] RecievedData = new byte[_Available];
switch (_Available)
{
case 0:
Close(_state);

Logger.wirte("接收到0包" + _state.Code+"正常退出");
return;
default:

int curRcv = 0;
int hasRecv=0;
int left =_Available;
//_handler.EndReceive(
while (hasRecv < _Available)
{
curRcv = _handler.Receive(RecievedData, hasRecv, left, SocketFlags.None);
left -= curRcv;
hasRecv += curRcv;
}
break;
}


try
{
byte[] temp = new byte[0];
_handler.BeginReceive(temp, 0, 0, 0, new AsyncCallback(ReadCallback), _state);//继续读取下一个数据
}
catch
{
this.Close(_state);
}

}
catch (Exception ex)
{
Logger.wirte(ex);
}
}
...全文
1656 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
starts_2000 2016-11-23
  • 打赏
  • 举报
回复
访问Available的时候,Socket有可能已经关闭了。 看看MSDN Available 的说明https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.available(VS.80).aspx
备注
如果当前使用的是非阻止 Socket,一种较好的做法是在调用 Receive 之前使用 Available 来确定数据是否排队等待读取。可用的数据即网络缓冲区中排队等待读取的全部数据。如果在网络缓冲区中没有排队的数据,则 Available 返回 0。
如果远程主机处于关机状态或关闭了连接,则 Available 会引发 SocketException。如果收到 SocketException,请使用 SocketException.ErrorCode 属性获取特定的错误代码。获取此代码后,您可以参考 MSDN Library 中的 Windows Sockets 第 2 版 API 错误代码文档,获取有关该错误的详细说明。
gs0038 2016-11-23
  • 打赏
  • 举报
回复
引用 3 楼 starfd 的回复:
在你的callback里面在进行socket的close呗 看你描述就是你的满足条件其实并不是真的满足了关闭条件,可能只是满足了你的业务条件,你忽略掉了后续处理过程
客户端不向服务端发送任何数据的情况下 callback是收不到消息,就不会执行到里面来。当然关闭会收到Available是0的外 所以要检查只能是外面检查。 上面竟然少一个字,非常严重的错哦,竟然 不能修改
gs0038 2016-11-23
  • 打赏
  • 举报
回复
引用 3 楼 starfd 的回复:
在你的callback里面在进行socket的close呗 看你描述就是你的满足条件其实并不是真的满足了关闭条件,可能只是满足了你的业务条件,你忽略掉了后续处理过程
客户端不向服务端发送任何数据的情况下 callback是收到消息,就不会执行到里面来。当然关闭会收到Available是0的外 所以要检查只能是外面检查。
  • 打赏
  • 举报
回复
在你的callback里面在进行socket的close呗 看你描述就是你的满足条件其实并不是真的满足了关闭条件,可能只是满足了你的业务条件,你忽略掉了后续处理过程
gs0038 2016-11-23
  • 打赏
  • 举报
回复
引用 1 楼 qq_33341938 的回复:
我也遇到这样的情况
那怎么办~
izhaorui 2016-11-23
  • 打赏
  • 举报
回复
我也遇到这样的情况
starts_2000 2016-11-23
  • 打赏
  • 举报
回复
引用 7 楼 gs0038 的回复:
[quote=引用 6 楼 starts_2000 的回复:] 访问Available的时候,Socket有可能已经关闭了。 看看MSDN Available 的说明https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.available(VS.80).aspx
备注
如果当前使用的是非阻止 Socket,一种较好的做法是在调用 Receive 之前使用 Available 来确定数据是否排队等待读取。可用的数据即网络缓冲区中排队等待读取的全部数据。如果在网络缓冲区中没有排队的数据,则 Available 返回 0。
如果远程主机处于关机状态或关闭了连接,则 Available 会引发 SocketException。如果收到 SocketException,请使用 SocketException.ErrorCode 属性获取特定的错误代码。获取此代码后,您可以参考 MSDN Library 中的 Windows Sockets 第 2 版 API 错误代码文档,获取有关该错误的详细说明。
这个msdn说的,我其实也看过了,我们就是使用非阻止方式,也是在Receive 之前使用 Available 来确定数据是否排队等待读取,我们使用的方式就是这样子的~ “访问Available的时候,Socket有可能已经关闭了。” 是的,有没有办法判断呢[/quote] 其实我的意思是使用 时,加上try catch,catch到错误就说明已经关闭了,后面就不需要处理了。
int _Available;
try
{
    _Available = _handler.Available;
}
catch
{
}
gs0038 2016-11-23
  • 打赏
  • 举报
回复
引用 6 楼 starts_2000 的回复:
访问Available的时候,Socket有可能已经关闭了。 看看MSDN Available 的说明https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.available(VS.80).aspx
备注
如果当前使用的是非阻止 Socket,一种较好的做法是在调用 Receive 之前使用 Available 来确定数据是否排队等待读取。可用的数据即网络缓冲区中排队等待读取的全部数据。如果在网络缓冲区中没有排队的数据,则 Available 返回 0。
如果远程主机处于关机状态或关闭了连接,则 Available 会引发 SocketException。如果收到 SocketException,请使用 SocketException.ErrorCode 属性获取特定的错误代码。获取此代码后,您可以参考 MSDN Library 中的 Windows Sockets 第 2 版 API 错误代码文档,获取有关该错误的详细说明。
啊哈,我想到了,其实可以自己加个属性来判断的,就在我关闭的同时设置一下这个客户端的属性记录一下,然后在接收的时候判断一下。。。。原来如此,我真是太历害了 ,哇哈哈
gs0038 2016-11-23
  • 打赏
  • 举报
回复
引用 6 楼 starts_2000 的回复:
访问Available的时候,Socket有可能已经关闭了。 看看MSDN Available 的说明https://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.available(VS.80).aspx
备注
如果当前使用的是非阻止 Socket,一种较好的做法是在调用 Receive 之前使用 Available 来确定数据是否排队等待读取。可用的数据即网络缓冲区中排队等待读取的全部数据。如果在网络缓冲区中没有排队的数据,则 Available 返回 0。
如果远程主机处于关机状态或关闭了连接,则 Available 会引发 SocketException。如果收到 SocketException,请使用 SocketException.ErrorCode 属性获取特定的错误代码。获取此代码后,您可以参考 MSDN Library 中的 Windows Sockets 第 2 版 API 错误代码文档,获取有关该错误的详细说明。
这个msdn说的,我其实也看过了,我们就是使用非阻止方式,也是在Receive 之前使用 Available 来确定数据是否排队等待读取,我们使用的方式就是这样子的~ “访问Available的时候,Socket有可能已经关闭了。” 是的,有没有办法判断呢
非常不错,c#入门经典哦! 关于socket的,适合初学者。 #socket编程基础 Microsoft.Net Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务,其字空间System.Net和System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要 --从socket套接字到普通的请求/响应,更重要的是,这种分层是可以扩展的,能够适应Internet不断扩展的需要。 抛开ISO/OSI模型的7层构架,单从TCP/IP模型上的逻辑层面上看,.Net类可以视为包含3个层次:请求/响应层、应用协议层、传输层。 WebReqeust和WebResponse 代表了请求/响应层,支持Http、Tcp和Udp的类组成了应用协议层,而Socket类处于传输层。 传输层位于这个结构的最底层,当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时,就需要使用这一层进行Socket套接字编程。 而在.Net中,System.Net.Sockets空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net空间中的所有其他网络访问类都建立在该套接字 Socket实现之上,如TCPClient、TCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多 Internet服务都可以见到Socket的踪影,如Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。 其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。 可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据; 针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉 Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用 Socket类开发windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。

110,549

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧