分类: C/C++
2008-08-07 17:40:33
CurReceLen=0; for(;;) { iResult=select(0,&fdread,NULL,NULL,&timeout); if(iResult==0) { AfxMessageBox("接收应答消息超时!!!",MB_OK|MB_ICONERROR); closesocket(Socket); return FALSE; } CurReceLen = recv(Socket, oBuf ReceLen, len, NO_FLAG_SET); if((CurReceLen>0) && (CurReceLen != SOCKET_ERROR)) { oBuf[ReceLen CurReceLen]=''\0''; memcpy((char *)&MsgLen,oBuf,sizeof(WORD32)); MsgLen=ntohl(MsgLen); if(ReceLen CurReceLen==MsgLen) { ReceLen =CurReceLen; break; } ReceLen =CurReceLen; } }在异步方式下,采用非阻塞方式实现比较方便,在非阻塞方式下可使用WSAAsyncSelect模型和WSAEventSelect模型:WSAAsyncSelect模型基于消息,WSAEventSelect模型基于事件,下面的示例代码设置了Socket进行读写和关闭操作的消息:
if (status == SOCKET_ERROR) { WriteLogFile("Set stream socket module fail!!!IP(%s), Port(%d) and error(%d)", GetIPAddr((PeerMap node)->IPAddr), (PeerMap node)->PeerPortNo, WSAGetLastError()); CloseSocket(TempSocket,__LINE__,__FILE__); return FALSE; }无论使用阻塞方式或非阻塞方式编程,需要重点考虑的一个问题:粘包现象,即应用发送两个或以上的数据包,在Socket通讯层将数据包合并成一个发送出去,因此接收端收到数据包以后需要对数据包根据应用定义的长度进行拆分,否则导致应用层丢包。
int tpcallex(char *svc, char *idata, long ilen, char **odata, long *olen, long flags, long timeout) { const int err_invoke_result = -1; int iHandler=0; int iResult=0; int iTimeOut=timeout; iHandler = tpacall((char *)svc, (char *)idata, ilen, (long)TPNOBLOCK); if(iHandler == err_invoke_result) { return iHandler; } while(iTimeOut>0) { iResult = tpgetrply(&iHandler, (char **)odata, olen, (long)TPNOBLOCK); if(iResult == err_invoke_result) { Sleep(10); iTimeOut -= 10; continue; } break; } if(iTimeOut<=0) { tpcancel(iHandler); return err_invoke_result; } return iHandler; }如果要增加接口的处理能力,使用多线程方式会存在隐患,最好的方式是采用多进程,不过存在如何消息均衡的问题。
if(!m_bFlatType) { for(i=paramNum,j=0;i>j;i--,j ) { VARIANTARG argTemp; VariantInit(&argTemp); argTemp=va[i-1]; va[i-1]=va[j]; va[j]=argTemp; } } params.cArgs = paramNum; params.rgvarg = va; params.cNamedArgs = 0; params.rgdispidNamedArgs = NULL; hr = SoapConnect.pSoapClient[index]->Invoke(dispidFn, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, ¶ms, &result, 0, 0); if(FAILED(hr)) { HandleHResult(_T("Invoke of " strService " method failed."), hr); VariantClear(&result); for(i=0;i三、总结
在三种通讯方式中,各有优缺点,但是主要还在于服务端采用什么技术方案来实现,接口必须对应采用相应的通讯模式。
除了上面的通讯模式,当然还有很多其它的方式,如管道、消息队列等,目前我在紧耦合的接口中使用得不多。 下载本文示例代码