同步
所谓同步,就是函数在发出一个功能调用过程时,在过程没有完成结束前,函数也是得不到返回的。按照这个定义,其实绝大多数函数都是同步调用(例如sin, isdigit等)。但是一般而言,我们在说同步、异步的时候,特指的是那些需要其他部件协作或者需要一定时间完成的任务。最常见的例子就是 SendMessage。该函数发送一个消息给某个窗口,在对方处理完消息之前(即是一个过程),这个函数不返回。当对方处理完毕以后,该函数才把消息处理函数所返回的 LRESULT值返回给调用者。
异步
就是函数在发出一个功能调用过程时,在过程没有完成结束前,函数也立即返回。以 CAsycSocket类为例(注意,CSocket从CAsyncSocket派生,但是起功能已经由异步转化为同步),当一个客户端通过调用 Connect函数发出一个连接请求后,调用者线程立刻可以朝下运行。当连接真正建立起来以后,socket底层会发送一个消息通知该对象。PostMessage()函数也是发送消息后立即返回的异步函数机制。
对同步与异步认识的形象例子:比如你住在一栋楼第三层,在上楼梯经过第二层时,要敲门给第二层一个阿姨东西。同步即是敲了门(发出消息),要等到阿姨从房里走出来并开门接了东西(消息处理过程),你才能继续上你住的第三层;而异步则是敲了门(发送消息),不等到阿姨从房里走出来并开门接了东西(消息处理过程),放下东西,就直接上你住的第三层。
阻塞与非阻塞的区别:用例子send与recv两个函数来说明
调用函数发送一定的Byte,在系统内部做的工作其实只是把数据传输(copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你copy过来的数据的话,这时候就体现出阻塞和非阻塞的不同之处了:对于阻塞模式的socket的send()函数将不返回直到系统缓冲区有足够的空间把你要发送的数据copy过去以后才返回,而对于非阻塞的socket的send()来说会立即返回WSAEWOULDDBLOCK告诉调用者说:“发送操作被阻塞了”,当然之后缓冲区够了还是发送出去了的,所以在通信编程时,这个不是个错误。对于recv()函数,同样道理,该函数的内部工作机制其实是在等待TCP/IP协议栈的接收缓冲区通知它说:“你的数据来了,对于阻塞模式的socket来说如果TCP/IP协议栈的接收缓冲区没有通知一个结果给它它就一直不返回:耗费着系统资源。。。而对于非阻塞模式的socket该函数会马上返回,然后告诉你:“WSAEWOULDDBLOCK,现在没有数据。。。”
1、CSocket及其基类CAsyncSocket采用Windows消息机制,即Socket事件通过Post消息方式发往内建的窗口,并在该窗口内调用虚函数OnAccept()、OnConnect()、OnSend()、OnReceive()和OnClose()等,所以CSocket所在的线程必须要有消息循环。
2、一个CSocket对象要在多个线程里传递时,不能直接传递(指针)。因为CSocket被尽力设计为线程安全的,它的内部句柄m_hSocket同一时刻只能被一个线程拥有。因此,在线程间应该传递句柄而不是指针。方法是:当前拥有CSocket对象的线程先Detach(),然后将返回的句柄传给另一线程。在另一线程中,再Attach()。
3、CSocket在多线程中使用时,请对VS6.0打SP5。因为不打SP5和打SP5,AfxSockInit()函数的内部实现源代码是不同的。而后者则支持多线程。并且每个用到CSocket的线程,请都调用AfxSockInit()
4、对一次OnReceive()事件,请将Socket内部缓冲区的到达数据接收完,否则可能导致以后OnReceive()不再触发。原因是:OnSend()、OnReceive()都是当缓冲区从有到无或者从无到有数据才触发的。
5、Socket内部的默认缓冲区大小一般是4096或者8192,默认值大小特性是我们关注的,虽然不必要知道究竟有多大,但得知道有这么个特性,因此,除非是一应一答的通信,你应该在发送和接收时组包(包括自己定义包的边界和标志等信息)。