CAsyncSocket使用总结 收藏
来源:互联网 发布:mac桌面文件丢失 编辑:程序博客网 时间:2024/05/22 18:59
CAsyncSocket使用总结 收藏
转载请注明出处blog.csdn.net/tianhai110
这几天都在研么MFC的套接字类CAsyncSocket的用法, 将一些心得和实践中遇到的问题总结一下。
一、
1.
2.
3.
4.
CAsyncSocket属于异步非阻塞类;
CSocket是MFC在CAsyncSocket基础上派生的一个同步阻塞Socket的封装类
二、
服务器端:
m_pListSocket
m_pListSocket-> Create( 端口,地址);
m_pListSocket->Listen();
m_pListSocket::OnAccept( )
...{
m_pSocket
m_pListSocket-> Accept(m_pSocket);
// m_pSocket 就相当于连接的那个客户端了
}
m_pSocket::OnRecive( int nErrorCode)
...{
...{
}
}
m_pSocket::OnSend()
...{
}
m_pListSocket->Close();
delete m_pListSocket;
delete m_pSocket;
客户端:
m_pClientSocket
m_pClientSocket -> Create( 端口,地址);
m_pClientSocket->Connect();
m_ pClientSocket::OnConnect()
...{
}
m_ pClientSocket::OnRecive( int nErrorCode)
...{
...{
}
}
m_pClientSocket::OnSend( int nErrorCode)
...{
}
m_pClientSocket->Close();
三、
由于CAsyncSocket采用的是异步非阻塞机制,所以你随时可以发包,也随时可能收到包。
发送、接收函数都是异步非阻塞的,顷刻就能完成,所以收发交错进行着。也正因为如此,仅调用它们并不能保障发送或接收的完成。
例如发送函数Send,调用它可能有3种结果:错误、部分完成、全部完成。其中错误又分两种情况:一种是由各种网络问题导致的失败,你需要马上决定是放弃本次操作,还是启用某种对策;另一种是“忙”,你实际上不用马上理睬。你需要调用GetLastError来判断是哪种情况,GetLastError返回WSAEWOULDBLOCK,代表“忙”,为什么当你Send得
到WSAEWOULDBLOCK却不用理睬呢?因为CAsyncSocket会记得你的SendWSAEWOULDBLOCK了,待发送的数据会写入CAsyncSocket内部的发送缓冲区,并会在不忙的时候自动调用OnSend,发送内部缓冲区里的数据。同样,如果Send只完成了一部分,你也不需要理睬,尚未发送的数据同样会写入CAsyncSocket内部的发送缓冲区,并在不“忙”的时候自动调用OnSend完成发送。
与OnSend协助Send完成工作一样,OnRecieve、OnConnect、OnAccept也会分别协助Recieve、Connect、Accept完成工作。这一切都通过消息机制完成。
在你使用CAsyncSocket之前,必须调用AfxSocketInit初始化WinSock环境,而AfxSocketInit会创建一个隐藏的CSocketWnd对象,由于这个对象由Cwnd派生,因此它能够接收Windows消息。一方面它会接受各个CAsyncSocket的状态报告,另一方面它能捕捉系统发出的各种SOCKET事件。所以它能够成为高层CAsyncSocket对象与WinSock底层之间的桥梁:例如某CAsyncSocket在Send时WSAEWOULDBLOCK了,它就会发送一条消息给CSocketWnd作为报告,CSocketWnd会维护一个报告登记表,当它收到底层WinSock发出的空闲消息时,就会检索报告登记表,然后直接调用报告者的OnSend函数。所以前文所说的CAsyncSocket会自动调用OnXxx,实际上是不对的,真正的调用者是CSocketWnd——它是一个CWnd对象,运行在独立的线程中。
四、
在理解了上面的机制后, 让我们了解下CAsyncSocket的通信流程;
如果每次发送的数据比较简单,不会造成WASEWOULDBLOCK(阻塞),不会触发OnSend;
因此小数据直接Send就行了,大数据就需要在OnSend判断数据发送是否正确;
如何手动触发OnSend()呢,采用AsyncSelect( FD_WRITE),通知CsocketWnd窗口处理写
数据操作; 同样AsyncSelect(FD_READ)将通知CsocketWnd窗口当有消息传来的时候触发OnRecevie();
五、
编程中遇到这个问题,发现很多人都遇到过这个问题。
症状如下:Socket连接后只能发送一次消息,发送第二次消息的时候,另一方就接收不到;
原因是:没有让Socket改变响应事件的发式
解决方法:在OnReceive()中,Receive()后调用AsyncSelect(FD_READ);
Void CMyAsyncSocket::OnReceive(int nErrorCode)
...{
}
或则 调用父类的OnReceive()
Void CMyAsyncSocket::OnReceive( int nErrorCode)
...{
}
六、
在创建服务器Socket的时候,只有采用SOCK_STREAM(字符流),Listen才能成功;
采用SOCK_DGRAM(数据报文)创建的Socket是面向无连接发式(UDP),所以Listen不成功(有待验证)
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/tianhai110/archive/2008/02/23/2115270.aspx
- CAsyncSocket使用总结 收藏
- CAsyncSocket使用总结
- CAsyncSocket使用总结
- CAsyncSocket使用总结
- CAsyncSocket使用总结
- Hibernate使用总结 收藏
- CAsyncSocket的封装使用
- CAsyncSocket
- CAsyncSocket
- CAsyncSocket
- CAsyncSocket
- CAsyncSocket
- CAsyncSocket
- CAsyncSocket
- Windows Sockets:使用 CAsyncSocket 类
- Windows Sockets:使用 CAsyncSocket 类
- [收藏]Socket API,CAsyncSocket,CSocket内幕及其用法
- [收藏]Socket API,CAsyncSocket,CSocket内幕及其用法
- 内核符号表解释
- JSP处理数据时间过长时对话框处理
- linux XFRM整体框架简单分析
- MySQL的存储过程
- 有密码和用户名却进不去共享文件(在进去过共享文件后,又修改了密码,导致没有共享文件的登录框)
- CAsyncSocket使用总结 收藏
- MySql分页存储过程
- 111116 VB WebBrowser 加入
- MySQL存储过程的控制语句
- poj Oulipo(KMP)
- Android Pixelflinger 研究
- Java多线程之Callable接口的实现
- ubuntu--fetion--qq
- ASP.NET内置对象