Socket C++ TCP阻塞 非阻塞总结(4)

2019-05-26 17:31

sin_port表示端口,如果参 数1为0,则WinSock分配一个端口给它,范围在1024和5000之间;域sin_addr是表示地址信 息,它是一个联合体,其中s_addr表示如下形式的字符串,“28.56.22.8”。如果参数没有 指定地址,则WinSock自动地得到本地IP地址(如果有几个网卡,则使用其中一个的地址) 。

(6)总结Create的过程

首先,调用socket函数创建一个socket;然后把创建的socket对象映射到CAsyncSocket对象 (捆绑在一起),指定本socket要通知的网络事件,并创建一个“socket窗口”来接收网络 事件消息,最后,指定socket的本地信息。

下一步,是使用成员函数Connect连接远地主机,配置socket的远地信息。函数Connect类似 于Bind,把指定的远地地址转换成SOCKADDR_IN对象表示的地址信息(包括网络字节序的转 换),然后调用WinSock函数Connect连接远地主机,配置socket的远地端口和远地IP地址。

3.异步网络事件的处理

当网络事件发生时,“socket窗口”接收WM_SOCKET_NOTIFY消息,消息处理函数 OnSocketNotify被调用。“socket窗口”的定义和消息处理是MFC实现的,这里不作详细的 讨论。

OnSocketNotify回调CAsyncSocket的成员函数DoCallBack,DoCallBack调用事件处理函数, 如OnRead、OnWrite等。摘录DoCallBack的一段代码如下:

switch (WSAGETSELECTEVENT(lParam))

{

case FD_READ:

{

DWORD nBytes;

//得到可以一次读取的字节数

pSocket->IOCtl(FIONREAD, &nBytes);

if (nBytes != 0)

pSocket->OnReceive(nErrorCode);

}

break;

case FD_WRITE:

pSocket->OnSend(nErrorCode);

break;

case FD_OOB:

pSocket->OnOutOfBandData(nErrorCode);

break;

case FD_ACCEPT:

pSocket->OnAccept(nErrorCode);

break;

case FD_CONNECT:

pSocket->OnConnect(nErrorCode);

break;

case FD_CLOSE:

pSocket->OnClose(nErrorCode);

break;

lParam是WM_SOCKET_NOFITY的消息参数,OnSocketNotify传递给函数DoCallBack,表示通知 事件。

函数IOCtl是CAsyncSocket的成员函数,用来对socket的I/O进行控制。这里的使用表示本次 调用Receive函数至多可以读nBytes个字节。

从上面的讨论可以看出,从创建socket到网络I/O,CAsyncSocket直接封装了低层的WinSock API,简化了WinSock编程,实现了一个异步操作的界面。如果希望某个操作是阻塞操作,则 在调用Create时不要指定该操作对应的网

络事件。例如,希望Connect和Send是阻塞操作, 在任务完成之后才返回,则可以使用如下的语句:

pSocket->Create(0, SOCK_STREAM,

FR_WRITE|FR_OOB|FR_ACCEPT|FR_CLOSE);

这样,在Connect和Send时,如果是用户界面线程的话,可能阻塞线程消息循环。所以,最 好在工作者线程中使用阻塞操作。

2.CSocket

如果希望在用户界面线程中使用阻塞socket,则可以使用CSocket。它在非阻塞socket基础之上实 现了阻塞操作,在阻塞期间实现了消息循环。

对于CSocket,处理网络事件通知的函数OnAccept、OnClose、OnReceive仍然可以使用, OnConnect、OnSend在CSocket中永远不会被调用,另外OnOutOfBandData在CSocket中不鼓励使用 。

CSocket对象在调用Connect、Send、Accept、Close、Receive等成员函数后,这些函数在完成任 务之后(连接被建立、数据被发送、连接请求被接收、socket被关闭、数据被读取)之后才会返 回。因此,Connect和Send不会导致OnConnect和OnSend被调用。如果覆盖虚拟函数OnReceive、 OnAccept、OnClose,不主动调用Receive、Accept、Close,则在网络事件到达之后导致对应的虚 拟函数被调用,虚拟函数的实现应该调用Receive、Accept、Close来完成操作。下面,就一个函 数Receive来考察CSocket如何实现阻塞操作和消息循环的。

int CSocket::Receive(void* lpBuf, int nBufLen, int nFlags)

{

//m_pbBlocking是CSocket的成员变量,用来标识当前是否正在进行

//阻塞操作。但不能同时进行两个阻塞操作。

if (m_pbBlocking != NULL)

{

WSASetLastError(WSAEINPROGRESS);

return FALSE;

}

//完成数据读取

int nResult;

while ((nResult = CAsyncSocket::Receive(lpBuf, nBufLen, nFlags))

== SOCKET_ERROR)

{

if (GetLastError() == WSAEWOULDBLOCK)

{

//进入消息循环,等待网络事件FD_READ

if (!PumpMessages(FD_READ))

return SOCKET_ERROR;

}

else

return SOCKET_ERROR;

}

return nResult;

}

其中:

参数1指定一个缓冲区保存读取的数据;参数2指定缓冲区的大小;参数3取值MSG_PEEK(数据拷贝 到缓冲区,但不从输入队列移走),或者MSG_OOB(处理带外数据),或者MSG_PEEK|MSG_OOB。

Receive函数首先判断当前CSocket对象是否正在处理一个阻塞操作,如果是,则返回错误 WSAEINPROGRESS;否则,开始数据读取的处理。

读取数据时,如果基类CAsyncSocket的Receive读取到了数据,则返回;否则,如

果返回一个错误 ,而且错误号是WSAEWOULDBLOCK,则表示操作阻塞,于是调用PumpMessage进入消息循环等待数据 到达(网络事件FD_READ发生)。数据到达之后退出消息循环,再次调用CAsyncSocket的Receive 读取数据,直到没有数据可读为止。

PumpMessages是CSocket的成员函数,它完成以下工作:

(1)设置m_pbBlocking,表示进入阻塞操作。

(2)进行消息循环,如果有以下事件发生则退出消息循环:收到指定定时器的定时事件消息 WM_TIMER,退出循环,返回TRUE;收到发送给本socket的消息WM_SOCKET_NOTIFY,网络事件 FD_CLOSE或者等待的网络事件发生,退出循环,返回TRUE;发送错误或者收到WM_QUIT消息,退出 循环,返回FALSE;

(3)在消息循环中,把WM_SOCKET_DEAD消息和发送给其他socket的通知消息WM_SOCKET_NOFITY放 进模块线程状态的通知消息列表m_listSocketNotifications,在阻塞操作完成之后处理;对其他 消息,则把它们送给目的窗口的窗口过程处理。

3.CSocketFile

MFC还提供了一个网络编程模式,可以充分利用CSocket的特性。该模式的基础是CSocketFile类。 使用方法如下:

首先,构造一个CSocket对象;调用Create函数创建一个socket对象(SOCK_STREAM类型)。

接着,如果是客户程序,调用Connect连接到远地主机;如果是服务器程序,先调用Listen监听 socket端口,收到连接请求后调用Accept接收请求。

然后,创建一个和CSocket对象关联的CSocketFile对象,创建一个和CSocketFile对象关联的 CArchive对象,指定CArchive对象是用于读或者写。如果既要读又要写,则创建两个CArchive对 象。

创建工作完成之后,使用CArchive对象在客户和服务器之间传送数据

使用完毕,销毁CArchive对象、CSocketFile对象、CSocket对象。

从前面的章节可以知道,CArchive可以以一个CFile对象为基础,通过<<和>>操作符完成对文件的 二进制 流的操作。所以可以从CFile派生一个类,实现CFile的操作界面(Read和Write)。由于CSocket 提供了阻 塞操作,所以完全可以像读写文件一样读写socket数据。


Socket C++ TCP阻塞 非阻塞总结(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:带式运输机上的 同轴式二级圆柱齿轮 减速器 之课程设计

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: