IPServer的实现3-机顶盒。

分析:要组播接收的方式接收交换机的数据。图像要显示出来(由于发送时设定了发送包的大小所以还要组包)。

接收数据和显示代码如下:

UINT ReceiveShowCh1(void *p)
{
	CMultSocket m_SocketCh;
	CCh1Dlg *pDlg=(CCh1Dlg*)p;
	CString m_strIP;
	CString m_strPort;
	pDlg->m_IPAddrCh1.GetWindowText(m_strIP);
	pDlg->m_PortCh1.GetWindowText(m_strPort);
	pDlg->m_Port1=atoi(m_strPort);
	
	CString strTemp;
	unsigned int IP_A;

	strTemp=m_strIP.Mid(0, m_strIP.Find('.',0));
	IP_A=atoi(strTemp);
	if(IP_A<224 || IP_A>239 || pDlg->m_Port1>65536)
	{
		AfxMessageBox("地址范围:224.0.0.0~239.255.255.254,端口号范围:0~65535");
		return -1;
	}
	/*设置组播接收*/
    int ret;
    SOCKET SockCh1;
    SOCKADDR_IN localAddr,remoteAddr;
    int len = sizeof SOCKADDR;
    char recvBuf[32000];
    ip_mreq  mcast;  // 设置组播

    SockCh1 = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if ( INVALID_SOCKET == SockCh1 )
    {
         WSACleanup();
         return 1;
    }
    localAddr.sin_family = AF_INET;
    localAddr.sin_port =  htons(pDlg->m_Port1);
    localAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

    ret = bind(SockCh1,(SOCKADDR*)&localAddr,len);
    if ( SOCKET_ERROR == ret )
    {
        closesocket(SockCh1);
        return -1;
    }

    //用于接收组播所设置,把套接字加入一个组播
    memset(&mcast,0x00,sizeof(mcast));
    mcast.imr_multiaddr.S_un.S_addr = inet_addr(m_strIP);
    mcast.imr_interface.S_un.S_addr = htonl(INADDR_ANY);
    ret = setsockopt(SockCh1,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mcast,sizeof(mcast));
    if ( SOCKET_ERROR == ret )
    {
        AfxMessageBox("Error IP_Add");//printf("IP_ADD_MEMBERSHIP ERROR! CODE IS : %d\n",WSAGetLastError());
        return -1;
    }

    memset(&remoteAddr,0x00,len);
    memset(recvBuf,0x00,sizeof(recvBuf));
	char *pBuf=new char[320000];
	int iTemp=0;

	int flags=0;
    while (1)
    {
        ret = recvfrom(SockCh1,recvBuf,sizeof(recvBuf),0,(SOCKADDR*)&remoteAddr,&len);
		if(flags)
		{
			if ( ret > 0 )
		    {        
				if(ret==1024)
				{
					for (int i=0; i<=ret; i++)
					{
						pBuf[i+iTemp] = recvBuf[i];
					}
					iTemp+=ret;
				}
				else
				{
					for (int i=0; i<=ret; i++)
					{
						pBuf[i+iTemp] = recvBuf[i];
					}
					iTemp+=ret;

					//显示接收内容
					pDlg->ShowPIC(pBuf,iTemp);
					iTemp=0;
				}
		     }
		}
		//过滤掉不完整的第一帧,一旦第一个小于1024的包,
		//认为为图片的最后一个包,下一个为图片开始,flags置位
		if(ret<1024)
		{
			flags=1; 
		}

   }	
	return 0;	
}

其中ShowPIC的代码如下:

void CCh1Dlg::ShowPIC(char* buf,int iSize)
{	
	IStream* m_pStream ;
	IPicture* m_pPicture ;
	LONG m_nWidth;
	LONG m_nHeight;
	HRESULT hr;

//上下文环境
    CWnd *pPic =GetDlgItem(IDC_STATIC_Picture1); pPic-> GetDC(); CClientDC dc(pPic);//CClientDC dc(this); CRect rc; HWND pWnd = pPic->GetSafeHwnd(); ::GetWindowRect(pWnd,&rc); m_pStream = NULL; m_pPicture = NULL; HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE,iSize);//开辟内存 hMem=buf; hr = ::CreateStreamOnHGlobal(hMem,TRUE,&m_pStream); ASSERT(SUCCEEDED(hr)); hr= ::OleLoadPicture(m_pStream,iSize,TRUE,IID_IPicture,(LPVOID *)&m_pPicture); ASSERT(hr==S_OK); //long nWidth,nHeight;宽高,MM_HIMETRIC 模式,单位是0.01毫米 m_pPicture->get_Width(&m_nWidth);//宽 m_pPicture->get_Height(&m_nHeight);//高 int w=rc.right-rc.left; int h=rc.bottom-rc.top;
   //根据窗口大小来显示 double tmppx=w*26.46; double tmppy=h*26.46; LONG px=(LONG)tmppx; LONG py=(LONG)tmppy; CSize sz(px,py);//图片显示的大小 dc.HIMETRICtoDP(&sz); // 转换 MM_HIMETRIC 模式单位为 MM_TEXT 像素单位 m_pPicture->Render(dc.m_hDC,0,0,sz.cx,sz.cy,0,m_nHeight,m_nWidth,-m_nHeight,NULL); }

到此结束了。这里只是贴了些部分实现的代码。自认写的不好很多可以改进的地方。贴出了就是想得到更多的改进。

PS:不管结果如何吧。过程那些只有我们能体会,还有,那个和我一起努力的兄弟,我们加油,我们要变的更强!~

posted on 2011-08-18 11:18  静幽独白  阅读(272)  评论(0编辑  收藏  举报

导航