我在服务器端用异步套接字监听连接
notifyReset.Reset();//这是ManualResetEvent对象
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ), ctlTcpSock );//ctlTcpSock是监听用的sock
notifyReset.WaitOne();
下面是回调方法
private void AcceptCallBack ( IAsyncResult ar )
{
notifyReset.Set ( ); //事件状态设为终止,允许一个或多个等待线程继续
Socket sockObj = (Socket)ar.AsyncState;
accpSock = sockObj.EndAccept ( ar );//异步接收传入的连接尝试,返回socket对象来处理于远程主机的通信
StateInfomation stInfo = new StateInfomation ( );//StateInfomation 是自定义的状态信息类
stInfo.WorkSock = accpSock;
AddToHostList ( chatComm );
Thread chatThd = new Thread ( new ThreadStart ( AcceptMsg ) );
chatThd.Start ( );
}
关闭时使用的是
ctlTcpSock.Close();accpSock = sockObj.EndAccept ( ar );一句出现异常:未处理ObjectDisposedException异常, 无法访问已释放的对象。对象名:“System.Net.Sockets.Socket”。
放在try块里不管他,反复监听断开(中间未建立连接),在ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ), ctlTcpSock )一句又出现同样异常。
好郁闷!
请哪位好心的兄弟指点一下如何解决 在下不胜感激(第一次发贴,昨天才注册 呵呵)
notifyReset.Reset();//这是ManualResetEvent对象
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ), ctlTcpSock );//ctlTcpSock是监听用的sock
notifyReset.WaitOne();
下面是回调方法
private void AcceptCallBack ( IAsyncResult ar )
{
notifyReset.Set ( ); //事件状态设为终止,允许一个或多个等待线程继续
Socket sockObj = (Socket)ar.AsyncState;
accpSock = sockObj.EndAccept ( ar );//异步接收传入的连接尝试,返回socket对象来处理于远程主机的通信
StateInfomation stInfo = new StateInfomation ( );//StateInfomation 是自定义的状态信息类
stInfo.WorkSock = accpSock;
AddToHostList ( chatComm );
Thread chatThd = new Thread ( new ThreadStart ( AcceptMsg ) );
chatThd.Start ( );
}
关闭时使用的是
ctlTcpSock.Close();accpSock = sockObj.EndAccept ( ar );一句出现异常:未处理ObjectDisposedException异常, 无法访问已释放的对象。对象名:“System.Net.Sockets.Socket”。
放在try块里不管他,反复监听断开(中间未建立连接),在ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ), ctlTcpSock )一句又出现同样异常。
好郁闷!
请哪位好心的兄弟指点一下如何解决 在下不胜感激(第一次发贴,昨天才注册 呵呵)
解决方案 »
- 如何在textbox中敲tab键完成正常的空格效果?绝顶高手速进!
- winform弹出的设置属性之类的对话框都是新建窗体么?
- wince c# Dll向应用程序返回Dll内运行的状态,显示在应用程序的状态栏里。
- [求助]怎么样把“Dataset”中某个列的部分数据赋值给一个数组?
- WinForm中连接sql数据库来匹配用户名和密码
- 怎样定义一个三维点(X、Y、Z三个坐标)的变量,并且把这个点转换为 object 类型?
- 如何查找到远程计算机上所有的共享文件夹.
- c#中如何才能使用coolbar控件或者如何使用其他方法实现coolbar控件的类似功能呢???????????送分!
- .net winform 超级疑惑的问题 高手来看看
- 请教小问题 奉上全部分数
- 如何设置panel隐藏的速度
- 请帮我看看这段代码,我搞不出来了,急呀
1. 如果我猜的没错,那么下面这段代码应该在一个循环里面:
notifyReset.Reset();//这是ManualResetEvent对象
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ),
tlTcpSock );//ctlTcpSock是监听用的sock
notifyReset.WaitOne();
2. 如果上面代码在一个循环里面,则当调用notifyReset.Set()并且
accpSock = sockObj.EndAccept ( ar );成功返回建立连接时,
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ),
tlTcpSock );
会被再次调用,即系统自动新开一个线程执行回调函数AcceptCallBack,并且停在
accpSock = sockObj.EndAccept ( ar );
的位置.
3. 当第一个连接使用完毕调用ctlTcpSock.Close();关闭连接时,系统将自动释放
ctlTcpSock对象所占用的资源,即该对象将被回收而不再可用.则此时当客户端发送一个创建连
接请求到服务器端的时候,系统将自动检测到accpSock = sockObj.EndAccept ( ar );,但此时
sockObj所引用的对象(即ctlTcpSock对象)已经不存在,所以会抛出ObjectDisposedException
异常。解决办法:
控制好同步.仔细看看msdn的例子就明白了,例子里面的状态对象的使用非常关键.
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ),
tlTcpSock );//ctlTcpSock是监听用的sock
notifyReset.WaitOne();
如果上面这段代码没在循环里面,则当多次调用ctlTcpSock.BeginAccept()方法也可能引发LZ所说的异常.
notifyReset.Reset();//这是ManualResetEvent对象
ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ),
tlTcpSock );//ctlTcpSock是监听用的sock
notifyReset.WaitOne();我的确是把他放到循环里了 因为服务器要接受多个客户端连接,经你提起我发现我是现关闭套接字后关闭循环的 呵呵 (因为我把设置循环条件和按钮状态放在了一个方法里,刚才把它单提了出来)
先关闭循环后关闭套接字,并捕获了accpSock = sockObj.EndAccept ( ar )的异常后,在反复监听断开时 ctlTcpSock.BeginAccept ( new AsyncCallback ( AcceptCallBack ), ctlTcpSock );一句就不会再产生异常了,但是那个“无法访问已释放的对象。”还是会出现。
我找了半天 终于让我找到了msdn的套接字代码示例,呵呵,看了一下 那里面用的是
Socket handler = (Socket) ar.AsyncState;
handler.Shutdown(SocketShutdown.Both);
handler.Close();
这几句是在SendCallback(IAsyncResult ar)方法中,示例是发送个信息后直接就关闭了,实际上肯定不能这么做啊。
我对ctlTcpSock用Shutdown()方法,产生异常:由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
说明不能未连接时就Shutdown(),只用ctlTcpSock还是会有“无法访问已释放的对象。”,不断开还不能正常退出~,好郁闷,我就是想解决一下socket监听后没建立连接怎么关闭它才能正常。
只用ctlTcpSock.Close()还是会有“无法访问已释放的对象。”
2.对于"无法访问已释放的对象."这个问题,可以这样解决:
a.调用Close()方法之后,讲ctlTcpSock置空,即ctlTcpSock = null;
b.在任何调用ctlTcpSock的属性或方法的地方判断它是否为空,不为空才执行操作,否则做相应处理.
上面的解决方法是比较差的.出现这问题就是我上面说的,你的同步没有做好.同步要讲的话要很大篇幅,你还是自己花时间看看示例中StateObject的使用吧.注意Socket定义成局部变量和全局变量的区别和作用.
listener.Listen(MAX_SOCKET); // Setup a callback to be notified of connection requests
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
/// <summary>
/// Callback used when a client requests a connection.
/// Accpet the connection, adding it to our list and setup to
/// accept more connections.
/// </summary>
/// <param name="ar"></param>
public void OnConnectRequest(IAsyncResult ar)
{ Socket listener = (Socket) ar.AsyncState;
NewConnection(listener.EndAccept(ar));
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
}
Close: if( m_sock != null && m_sock.Connected )
{
m_sock.Shutdown( SocketShutdown.Both );
m_sock.Close();
}
刚才想到一个问题,异步套接字是不是很多时候能自动释放,,想到这个的原因是:我用客户端连接服务器,连接后没有断开,也就是没有关闭socket,点退出(里面是application.exit),这样居然也可以正常退出了 进程里看不到客户端了,这是怎么回事呢。其实我是最近才开始尝试使用一下异步套接字的,因为原来使用同步套接字的时候accept总是阻塞,结束他就要有异常,现在异步的异常似乎更多,崩溃中~!
麻烦星空大哥再指点指点~
2.Socket是要你手动释放的,之所以你能正常退出是因为你调用过Close(),该方法无论是客户端还是服务器端调用都可以正常释放连接.
3.异步是非常复杂的,我4月份刚刚完成一个项目,里面的上传下载就是用的异步Socket,花了我很多时间学习,建议你要学异步的话可以看看MSDN里面关于"异步编程"的内容,这是一个比较大的课题.
谢谢大家了 尤其 AtaLoss0202(星空天宇),