www.pudn.com > H264RtpSource.rar > AllProtocol.cpp
#include "StdAfx.h"
#include ".\allprotocol.h"
#include "typedef.h"
#include "MySafeDefine.h"
#include "Queue.h"
#include "rtp_type.h"
//心跳时间
#define TIME_PULSE 20
#define RTP_PAYLOAD_VIDEO_H264 36 //h.264视频码流payload type
#define RTP_PAYLOAD_AUDIO_AAC 37 //aac音频码流payload type
#define RTP_HEADER_SIZE 12
#define H264_Get_NalType(c) ((c)&0x1f)
#define PLAY_ADD_AUDIO(flag) (flag = flag|0x02)
#define PLAY_ADD_VIDEO(flag) (flag = flag&0xfb)
#define PLAY_DEL_AUDIO(flag) (flag = flag&0xfd)
#define PLAY_DEL_VIDEO(flag) (flag = flag|0x04)
#define GET_AUDIO_FLAG(value) ((value & 0x02)>>1)
#define GET_VIDEO_FLAG(value) ((value & 0x04)>>2)
//客户端连接状态
const int LINK_STATUS_STOP =0;
const int LINK_STATUS_LINKING =1;
const int LINK_STATUS_LINKED =2;
typedef struct _RECVBUF
{
int OperatorCode;
char Buf[1500];
}RECVBUF;
CAllProtocol::CAllProtocol(void)
:m_SocketTCP(INVALID_SOCKET)
,m_SocketRTP(INVALID_SOCKET)
,m_RemotePort(3320)
,m_LocalPort(8000)
,m_RemoteIp("192.168.0.130")
,m_LocalIp(0)
,m_hGetDataThreadId(NULL)
,bFinishThread(TRUE)
,m_iLinkStatus(LINK_STATUS_STOP)
,tmLastSendPulse(0)
,bConnectRestart(FALSE)
,m_VideoQueue(NULL)
,SPS_GET(FALSE)
,VideoFrameNum(0)
,m_bFirstFrame(TRUE)
{
//网络通讯初始化
WORD wVersionRequested;
WSADATA wsadata;
int iRetCode;
wVersionRequested = MAKEWORD(1,1);
iRetCode = WSAStartup(wVersionRequested,&wsadata);
if (iRetCode!=0)
{
WSACleanup();
}
m_VideoQueue = new CGoldQueue();
initFIFO();
//得到本机的IP地址,因为RTP服务端需要
//取得本地的IP地址
char strHost[80];
gethostname(strHost,80);
hostent *pAddressInfo = gethostbyname(strHost);
m_LocalIp = (*(struct in_addr *)pAddressInfo->h_addr_list[0]).S_un.S_addr;
}
CAllProtocol::~CAllProtocol(void)
{
//在结束这个实例的时候,我们要关闭SOCKET
SAFE_CLOSESOCKET(m_SocketRTP);
SAFE_CLOSESOCKET(m_SocketTCP);
if (m_VideoQueue!=NULL)
{
SAFE_DELETE(m_VideoQueue);
}
WSACleanup();
}
//TCP连接服务器
//采用非阻塞通讯,这样连接服务器效率更高
//
int CAllProtocol::ConnectTCP()
{
//初始化一个SOCKET
m_SocketTCP = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (m_SocketTCP == INVALID_SOCKET)return -1;
//设置SOCKET选项
BOOL ReuseAddress = 1;
//设置一个ip地址可以被多个套接字使用
if (setsockopt(m_SocketTCP,SOL_SOCKET,SO_REUSEADDR,(char *)&ReuseAddress,sizeof(ReuseAddress)) == SOCKET_ERROR)return -1;
int opt = 1;
if (setsockopt(m_SocketTCP,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(opt)) == SOCKET_ERROR)return -1;
//绑定通讯地址
sockaddr_in sockAddr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(m_RemotePort);
sockAddr.sin_addr.S_un.S_addr = inet_addr(m_RemoteIp);
//设置非阻塞
unsigned long nonBlocked = 1;
if (ioctlsocket(m_SocketTCP,FIONBIO ,&nonBlocked) == SOCKET_ERROR)return -1;
if(connect(m_SocketTCP,(sockaddr *)&sockAddr,sizeof(sockAddr))== SOCKET_ERROR)
{
if(WSAGetLastError() != WSAEWOULDBLOCK)return -1;
}
////////////////////////////////////////////////////////////////////////////////
int reval = -1;
struct timeval WaitVal;
fd_set WriteSet;
fd_set ExceptSet;
time_t TimeNow;
time_t TimeOut;
time(&TimeNow);
TimeOut = TimeNow + 1;
do
{
//清空fd_set与所有文件句柄的联系
FD_ZERO(&WriteSet);
FD_ZERO(&ExceptSet);
//建立sock句柄与fd_set的联系
FD_SET(m_SocketTCP, &WriteSet);
FD_SET(m_SocketTCP, &ExceptSet);
WaitVal.tv_sec = 0;
WaitVal.tv_usec = 1000 * 200L;
//select函数常常用在用一个进程监听多个服务器端socket。
reval = select((int)m_SocketTCP + 1, NULL, &WriteSet, &ExceptSet,&WaitVal);
if (reval == SOCKET_ERROR)
{
return -1;
}
else if ( reval == 0)
{
time(&TimeNow);
}else if ( reval > 0)
{
m_iLinkStatus = LINK_STATUS_LINKING;
return 1;
}
} while (TimeNow < TimeOut);
//这个地方采用非组塞通讯,可以判断服务器是存在的,但还没有确定连上;
//所以我们把连接的状态设置成为正在连接
return -1;
}
//RTP接收数据的初始化
int CAllProtocol::ConnectRTP()
{
//初始化一个SOCKET
m_SocketRTP = socket(AF_INET,SOCK_DGRAM,0);
if (m_SocketRTP==INVALID_SOCKET)return -1;
BOOL ReuseAddress = 1;
int nBufSize = 1500*50;
unsigned long nonBlocked = 1;
//设置SOCKET为,非阻塞通讯
if (ioctlsocket(m_SocketRTP,FIONBIO ,&nonBlocked) == SOCKET_ERROR)return -1;
if (setsockopt(m_SocketRTP,SOL_SOCKET,SO_REUSEADDR,(char *)&ReuseAddress,sizeof(ReuseAddress)) == SOCKET_ERROR)return -1;
if (setsockopt(m_SocketRTP,SOL_SOCKET,SO_RCVBUF,(char *)&nBufSize,sizeof(nBufSize)) == SOCKET_ERROR)return -1;
sockaddr_in sockAddr;
ZeroMemory(&sockAddr,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(m_LocalPort);
sockAddr.sin_addr.s_addr = INADDR_ANY;
if (bind(m_SocketRTP,(sockaddr *)&sockAddr,sizeof(sockAddr)) == SOCKET_ERROR)return -1;
return 1;
}
//发送TCP数据,当这个函数返回SOCKET_ERROR的时候,我们让函数重新连接。
int CAllProtocol::SendTcpData(SOCKET Sock, const char* Data, int Length)
{
int lens = Length;
int sentLen = 0;
const char *buf = Data;
int nRetVal = 0;
fd_set fdsWrite;
timeval tv;
//如果这个SOCKET都不存在,那么赶快返回
if (Sock==SOCKET_ERROR)return SOCKET_ERROR;
while(lens > 0)
{
FD_ZERO(&fdsWrite);
FD_SET(Sock,&fdsWrite);
tv.tv_sec = 0;
tv.tv_usec = 300;
nRetVal = select(0,NULL,&fdsWrite,NULL,&tv);
if(nRetVal == SOCKET_ERROR)
{
return SOCKET_ERROR;
}
else if (nRetVal > 0)
{
if(FD_ISSET(Sock,&fdsWrite))
{
nRetVal = send(Sock , buf + sentLen ,lens ,0);
if(nRetVal != SOCKET_ERROR)
{
lens -= nRetVal;
sentLen += nRetVal;
}
else
{
return SOCKET_ERROR;
}
}
}
}
return Length;
}
//开启线程
int CAllProtocol::OpenThread()
{
//如果线程标志没有为false,则退出创建线程
if (!bFinishThread)return 0;
//线程结束标志为真,但是线程句柄又不NULL,
//此时我们要Close这个句柄
if (m_hGetDataThreadId!=NULL)CloseThread();
//现在开始可以创建线程了,并让线程挂起
m_hGetDataThreadId = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadGetDataEntry,this,CREATE_SUSPENDED,NULL);
if(m_hGetDataThreadId)
{
bFinishThread = FALSE;
::SetThreadPriority(m_hGetDataThreadId,THREAD_PRIORITY_ABOVE_NORMAL);
::ResumeThread(m_hGetDataThreadId); //线程重新开始
}else{
return -1;
}
return 1;
}
//关闭线程
BOOL CAllProtocol::CloseThread()
{
//等待线程结束
bFinishThread = TRUE; //线程标志为真,准备结束线程
WaitForSingleObject(m_hGetDataThreadId,INFINITE);
if (m_hGetDataThreadId!=NULL)
{
CloseHandle(m_hGetDataThreadId);
m_hGetDataThreadId = NULL;
}
return TRUE;
}
//线程函数;
DWORD CAllProtocol::ThreadGetDataEntry(LPVOID pv)
{
(reinterpret_cast(pv))->ThreadGetDataProc();
return 0;
}
//线程功能模块实现过程函数
//在这个线程中,我们要考虑到以下这几种情况:
//1、服务器还正在连接中;2、要重新建立连接;3、要退出线程;
void CAllProtocol::ThreadGetDataProc(void)
{
//我们采用for循环可能效率高一点
//等待和服务器建立连接
for (;;)
{
//说明要退出线程,我们只要退出for循环就可以
//没有什么要做,相应的处理,因为在别的地方都做了
if (bFinishThread == TRUE)break;
//线程启动了,但是我们必须注意,可能现在服务端现在还没有连接上
//还没有和服务器建立连接的意思
if (m_iLinkStatus == LINK_STATUS_STOP)
{
Sleep(10);
continue;
}else{
break;
}
}
//采集数据
for(;;)
{
//说明要退出线程,我们只要退出for循环就可以,
//没有什么要做,相应的处理,因为在别的地方都做了
if (bFinishThread == TRUE)break;
//这个地方说明和服务器建立连接可能出现了问题
//需要重新连接
if (bConnectRestart)
{
//如果重新连接不成功,那么我们继续重新连接
if (!RestartConnnect())continue;
}
//这里跟TCP没什么关系,最重要的是RTP数据的采集
int ifds = 0;
fd_set fdsRead/*,fdsWrite*/;
timeval tv;
FD_ZERO(&fdsRead);
//FD_ZERO(&fdsWrite);
//如果SOCKET是坏的,让他继续循环;
//出现这种情况的原因可能是:a,用户关闭了SOCKET链接;
if (m_SocketRTP == INVALID_SOCKET)continue; //不要再往下,执行了;
FD_SET(m_SocketRTP,&fdsRead);
ifds++;
tv.tv_sec = 0;
tv.tv_usec = 100000;
//只管读数据
int iRetCode = select(ifds,&fdsRead,NULL,NULL,&tv);
if (iRetCode == -1)
{
iRetCode = WSAGetLastError();
continue;
}else{
if ((FD_ISSET(m_SocketRTP,&fdsRead)))
{
//有数据可以采集了
RecvRtpPacket();
}
}
//发送心跳
time_t tmNow = time(NULL);
/*if (m_iLinkStatus == LINK_STATUS_LINKED)
{*/
if (tmNow -tmLastSendPulse >= TIME_PULSE)
{
//如果发送心跳没有成功,那么我们重新开始建立连接
if (SendPulse())
{
tmLastSendPulse = tmNow;
}else
{
//需要重新连接
//设置连接状态
m_iLinkStatus = LINK_STATUS_STOP;
//设置重连标志
bConnectRestart = TRUE;
}
}
/*}*/
}//结束 for
}
//发送客户端心跳
int CAllProtocol::SendPulse()
{
//如果TCP没有连接好,那么就不要发送心跳了
if (m_iLinkStatus == LINK_STATUS_STOP)return SOCKET_ERROR;
//发送心跳可能有点问题,如果出现服务端连接,20,30秒后,退出
//那么要看看是不是服务端出现了问题
PACKET_TYPE Packet;
ZeroMemory(&Packet,sizeof(Packet));
Packet.ProtocolType = 0x33;
Packet.PacketType = TYPE_REQUEST;
int iRetVal = SendTcpData(m_SocketTCP, (const char*)&Packet, PACKET_HEAD);
if(iRetVal == SOCKET_ERROR)return SOCKET_ERROR;
return 1;
}
//和重新服务器建立连接的函数
BOOL CAllProtocol::RestartConnnect()
{
//这里我们和服务器连接一次就算了,如果不成功返回FALSE
int iRetCode = -1;
//要想重新建立连接,先把一些东西初始化
SAFE_CLOSESOCKET(m_SocketTCP);
SAFE_CLOSESOCKET(m_SocketRTP);
iRetCode = ConnectTCP();
if (!iRetCode)return FALSE;
iRetCode = ConnectRTP();
if (!iRetCode)return FALSE;
//告诉服务端,可以发送视频数据
//连接上了,就不要在重新连接了
bConnectRestart = FALSE;
return TRUE;
}
//接收RTP数据
//输入参数:
//输出参数:
void CAllProtocol::RecvRtpPacket()
{
rtp_header_t* rtp;
unsigned char RecvBuf[2004];
//如果线程要结束,那么赶快退出这个函数
if (bFinishThread)return;
int iRecvLen = recvfrom(m_SocketRTP,(char *)RecvBuf,sizeof(RecvBuf),0,NULL,NULL);
if (iRecvLen == SOCKET_ERROR)
{
int nError = WSAGetLastError();
SAFE_CLOSESOCKET(m_SocketRTP);
//重新建立RTP连接
ConnectRTP();
return;
}
//判断是不是视频数据
rtp = (rtp_header_t*)RecvBuf;
//说明我们接收到得是视频数据
if (rtp->paytype == RTP_PAYLOAD_VIDEO_H264)
{
if ( !SPS_GET ) //如果没找到第一个i帧,就嫁出
{
if (7 != H264_Get_NalType(RecvBuf[20]))return;
SPS_GET = 1;
}
/////////////////////////////////////////////////////////////////////////////////////
//下面这段代码需要改进,这里很有可能会引起错误:比如图象失真。
//把数据写入FIFO
mu_write_pes_fifo(RecvBuf,iRecvLen);
if (rtp->markbit)VideoFrameNum++; //找到一帧数据
if (VideoFrameNum>=1)
{
//把数据处理出来
DealVideo();
}
}
}
//连接好,告诉服务端可以发送视频数据或音频数据,但是我们这个只有视频数据
BOOL CAllProtocol::USRStartPlay(unsigned char StartFlag)
{
//如果最基本的TCP连接没有,那么退出这个函数
if (m_iLinkStatus == LINK_STATUS_STOP)return FALSE;
int iRetCode = -1;
PLAY_REQUEST play_request;
memset(&play_request, 0, sizeof(PLAY_REQUEST));
play_request.IP =/* inet_addr("192.168.0.16");*/m_LocalIp;
play_request.Port = htons(m_LocalPort);
if(1 == GET_AUDIO_FLAG(StartFlag))
{
PLAY_ADD_AUDIO(play_request.StartOrEnd);
}
else
{
PLAY_DEL_AUDIO(play_request.StartOrEnd);
}
if( 0 == GET_VIDEO_FLAG(StartFlag) )
{
PLAY_ADD_VIDEO(play_request.StartOrEnd);
}
else
{
PLAY_DEL_VIDEO(play_request.StartOrEnd);
}
//当网络断开重新连接后,这个标志可以告诉服务端需要发送的是视频还是音视频数据
//但是这个filter中,没有用到
//m_StartFlag = play_request.StartOrEnd;
//开始发送数据
iRetCode = SendTcpPacket(m_SocketTCP,(char*)&play_request,sizeof(play_request),OP0041);
if (iRetCode<0)return FALSE;
//数据发送成功,说明连接已经建立好了
if (m_iLinkStatus == LINK_STATUS_LINKING)m_iLinkStatus = LINK_STATUS_LINKED;
//接收服务端的应答数据,确定服务端已经响应了,我们的请求
//这个数据只有数据头
PACKET_TYPE TempPacket;
ZeroMemory(&TempPacket,sizeof(PACKET_TYPE));
iRetCode = RecvTcpData(m_SocketTCP,(char*)&TempPacket,PACKET_HEAD);
if (iRetCode<=0)
{
return FALSE;
}
return TRUE;
}
//发送数据包,
int CAllProtocol::SendTcpPacket(SOCKET sock, char* usrbuf, int len, unsigned short OperatorType)
{
PACKET_TYPE TempPacket;
memset(&TempPacket, 0, sizeof(PACKET_TYPE));
TempPacket.PacketType = 0x33;
TempPacket.OperationCode = OperatorType;
TempPacket.DataLength = len;
if(len > 0)
{
memcpy(TempPacket.DataBuffer, usrbuf, len);
}
return SendTcpData(sock,(char*)&TempPacket,len+PACKET_HEAD);
}
//接收一定长度的TCP数据:如果成功返回接收的长度;没有数据返回0;SOCKET出错返回-1;
//SOCKET出错的时候,本应该重新连接,但考虑到,我们统一在发送心跳不成功的时候重连,
//所以这个地方我们就不做重新连接了。
int CAllProtocol::RecvTcpData(SOCKET Sock,char* Data,int Length)
{
if (Sock==INVALID_SOCKET)return -1;
int iRetCode;
fd_set fdsRead;
time_t tmNow;
time_t tmOut;
struct timeval WaitVal;
char RevData[2000];
//得到当前时间
time(&tmNow);
//异常时间
tmOut = tmNow + 2; // 整个接收过程2秒
do
{
int ifds =0;
FD_ZERO(&fdsRead);
FD_SET(Sock,&fdsRead);
ifds++;
WaitVal.tv_sec = 0; //秒
WaitVal.tv_usec = 1000 * 200L; //毫秒
iRetCode = select(ifds,&fdsRead,NULL,NULL,&WaitVal); //超时返回:0;有数据:>0;SOCKET出错:<0;
if (iRetCode==0)
{
time(&tmNow);
continue;
}
if ((iRetCode==INVALID_SOCKET)||((iRetCode > 0) &&(!FD_ISSET(Sock, &fdsRead))))
{
return -1;
}else{
//开始接受数据
ZeroMemory(RevData,2000);
iRetCode = recv(Sock,RevData,Length,0);
if (iRetCode == SOCKET_ERROR)return -1;
memcpy(Data,RevData,iRetCode);
break;
}
} while(tmNow0;SOCKET出错:<0;
if (iRetCode>0)
{
iRetCode = recv(Sock,tmpbuf,1500,0);
if (iRetCode<=0)break;
}else{
break;
}
}
}
////FIFO队列,这是一个比较经得起考验的FIFO
//网络中接收到的原始数据
void CAllProtocol::initFIFO()
{
RtpPacketFifo.Read = 0;
RtpPacketFifo.Write = 0;
RtpPacketFifo.DatCount = 0;
}
BOOL CAllProtocol::mu_write_pes_fifo(unsigned char *dat,int len)
{
//unsigned int EmptyLen;
unsigned int WriteByteCount=0;
if(RtpPacketFifo.DatCount < 20)
{
memcpy(RtpPacketFifo.Buf[RtpPacketFifo.Write],dat,/*2000*/len);
RtpPacketFifo.iDataLen[RtpPacketFifo.Write] = len;
RtpPacketFifo.Write++;
RtpPacketFifo.Write %= (20); //小技巧
RtpPacketFifo.DatCount++;
}else
{
/* Sleep(30);*/
return FALSE;
}
return TRUE;
}
BOOL CAllProtocol::mu_read_pes_fifo(unsigned char **Buf,int &len)
{
if (RtpPacketFifo.DatCount>0)
{
*Buf = RtpPacketFifo.Buf[RtpPacketFifo.Read];
len = RtpPacketFifo.iDataLen[RtpPacketFifo.Read];
RtpPacketFifo.Read++;
RtpPacketFifo.Read %= (20); //小技巧
RtpPacketFifo.DatCount--;
return TRUE;
}
return FALSE;
}
////FIFO队列 结束
//纯粹的视频处理函数
void CAllProtocol::DealVideo()
{
rtp_header_t* rtp;
unsigned char *pBuf = NULL;
unsigned char* p;
int time_stamp;
int FrameLen;
int headlen = RTP_HEADER_SIZE+sizeof(Payload_Mode_a);
pBuf = new unsigned char[1024*1024];
p = pBuf;
for (;;)
{
unsigned char *pData = NULL;
int lenData;
//读取数据
if (!mu_read_pes_fifo(&pData,lenData))
{
VideoFrameNum =0;
//没有读到数据,那么退出并释放内存
SAFE_DELETE(pBuf);
return;
}
rtp = (rtp_header_t*)pData;
memcpy( p, pData+headlen, lenData-headlen );
p += (lenData-headlen);
if (rtp->markbit)
{
time_stamp = rtp->timestamp;
FrameLen = int(p-pBuf);
break;
}
}
VideoFrameNum--; //减掉一个视频数据
//如果队列里面的数据量大于15了,此时我们最好对掉这帧数据
if (m_VideoQueue->GetCount()<10)
{
//已取到一帧, 加入帧队列
CGoldNode *tempNode = new CGoldNode( pBuf, FrameLen ,time_stamp);
m_VideoQueue->PutNode(tempNode);
}
//删除分配的内存
SAFE_DELETE(pBuf);
}
//读取一帧H264数据
//输入参数:无
//输出参数:
// pNode:H264帧数据
//返回值:
// 0:帧缓冲空,无法取得数据
// >0:取得帧数据
CGoldNode* CAllProtocol::GetFrame()
{
CGoldNode* pNode;
//安全一点
if (m_VideoQueue==NULL)return NULL;
//判断是否是第一帧数据
if(m_bFirstFrame)
{
//如果是看数据个数是否大于3;
if(m_VideoQueue->GetCount() < 2)
{
return NULL;
}
m_bFirstFrame = FALSE;
}
else
{
// There is no frame in the receive queue
if (m_VideoQueue->GetCount() == 0) return NULL;
}
#ifdef _DEBUG
char db_buf[100];
sprintf(db_buf, "队列中的数据帧数:%d\n", m_VideoQueue->GetCount());
//OutputDebugString(db_buf);
#endif
//如果队列中视频数据的帧数大于5,我们可以考虑把视频数据丢掉
DWORD RetValue = 0;
//得到一帧数据
if (m_VideoQueue->GetNode(&pNode))
{
return pNode;
}else{
return NULL;
}
}
//关闭和服务端的链接
void CAllProtocol::CloseConnect(void)
{
SAFE_CLOSESOCKET(m_SocketTCP);
SAFE_CLOSESOCKET(m_SocketRTP);
}
//调用这个函数设置客户端的服务器IP地址和端口号
void CAllProtocol::SetServerAddrr(char* RemoteIp,unsigned short RemotePort)
{
m_RemoteIp = RemoteIp;
m_RemotePort = RemotePort;
}
//接口: 用户通过这个函数设置RTP数据采集的端口号
void CAllProtocol::SetRTPPort(unsigned short LocalPort)
{
m_LocalPort = LocalPort;
}
//接口: 用户调用这个函数,开始链接服务器
BOOL CAllProtocol::USRStart(char *IPaddr, int port)
{
int iRetCode = -1;
//设置服务器地址
SetServerAddrr(IPaddr,port);
iRetCode = ConnectTCP();
if (iRetCode<0)return FALSE;
//USRStartPlay(0);
iRetCode = ConnectRTP();
if (iRetCode<0)return FALSE;
return TRUE;
}
//接口: 断开和服务端的链接
BOOL CAllProtocol::USRStop()
{
CloseConnect();
return TRUE;
}
BOOL CAllProtocol::GetPicture(PICTURE *pic)
{
//首先判断TCP SOCKET是否还存在
if (m_SocketTCP == INVALID_SOCKET)return FALSE;
ClearTcpDataBuf(m_SocketTCP);
int iRet;
PACKET_TYPE TempPacket;
memset(&TempPacket, 0, sizeof(PACKET_TYPE));
TempPacket.PacketType = 0x33;
TempPacket.OperationCode = OP0047; //查询图象参数
iRet = SendTcpData(m_SocketTCP,(char*)&TempPacket,PACKET_HEAD);
if (iRet != PACKET_HEAD)return FALSE; //发送数据不成功
//等待返回的数据
PICTURE_LOOK_RESPONSE look_response;
RECVBUF RecvBuf;
ZeroMemory(&look_response,sizeof(PICTURE_LOOK_RESPONSE));
ZeroMemory(&RecvBuf,sizeof(RECVBUF));
ZeroMemory(&TempPacket,sizeof(PACKET_TYPE));
//接收数据头
iRet = RecvTcpData(m_SocketTCP,(char*)&TempPacket, PACKET_HEAD);
if (iRet != PACKET_HEAD)return FALSE; //接收头失败
if (TempPacket.OperationCode != OP0047)return FALSE;
//接收数据
iRet = RecvTcpData(m_SocketTCP,RecvBuf.Buf,TempPacket.DataLength);
if (iRet>0)
{
/*if (RecvBuf.OperatorCode == OP0047)
{*/
memcpy(&look_response, RecvBuf.Buf, sizeof(PICTURE_LOOK_RESPONSE));
memcpy(pic, &look_response.Picture, sizeof(PICTURE));
return TRUE;
/*}*/
}
return FALSE;
}
BOOL CAllProtocol::SetPicture(PICTURE *pic)
{
//首先判断TCP SOCKET是否还存在
if (m_SocketTCP == INVALID_SOCKET)return FALSE;
ClearTcpDataBuf(m_SocketTCP);
int iRet;
int SenLen;
PICTURE_DATA_REQUEST PicReq;
PACKET_TYPE TempPacket;
SenLen = sizeof(PICTURE_DATA_REQUEST);
memset(&PicReq, 0, sizeof(PICTURE_DATA_REQUEST));
memcpy(&PicReq.Picture, pic, sizeof(PICTURE));
memset(&TempPacket, 0, sizeof(PACKET_TYPE));
TempPacket.PacketType = 0x33;
TempPacket.OperationCode = OP0046; //设置图象参数
TempPacket.DataLength = sizeof(PICTURE_DATA_REQUEST);
memcpy(TempPacket.DataBuffer, &PicReq, sizeof(PICTURE_DATA_REQUEST));
iRet = SendTcpData(m_SocketTCP,(char*)&TempPacket,PACKET_HEAD+SenLen);
if (iRet != (PACKET_HEAD+SenLen))return FALSE; //发送数据不成功
PICTURE_DATA_RESPONSE PicResp;
RECVBUF RecvBuf;
ZeroMemory(&PicResp,sizeof(PICTURE_DATA_RESPONSE));
ZeroMemory(&RecvBuf,sizeof(RECVBUF));
iRet = RecvTcpData(m_SocketTCP,(char*)&RecvBuf,sizeof(RECVBUF));
if (iRet>0)
{
/*if (RecvBuf.OperatorCode == OP0047)
{*/
//memcpy(&PicResp, RecvBuf.Buf, sizeof(PICTURE_DATA_RESPONSE));
return TRUE;
/*}*/
}
return FALSE;
}
int CAllProtocol::ControlPlatform(unsigned char Action, int Step)
{
//首先判断TCP SOCKET是否还存在
//if (m_SocketTCP == INVALID_SOCKET)return FALSE;
//ClearTcpDataBuf(m_SocketTCP);
//int iRet;
//PLATFORM_REQUEST plat_request;
//memset(&plat_request, 0, sizeof(PLATFORM_REQUEST));
//plat_request.Platform.Direction = Action;
return 1;
}