首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 即時桌面廣播教學系統:JPEG 壓縮與非同步 UDP 傳輸

     編輯:VC 教學

系統概述

教師端擷取桌面畫面 → JPEG 壓縮 → UDP 廣播傳送 → 學生端接收解壓 → 即時顯示。採用非同步 Socket (CAsyncSocket) 避免阻塞 UI,自訂簡易 JPEG 壓縮演算法提升區域網路傳輸效率。

教師端 (發送器) 實作

1. 專案建立

  • MFC AppWizard → Dialog-based 專案 Netss,勾選 Windows Sockets 支援。

2. 核心類別與變數


class CSendSocket : public CAsyncSocket
{
public:
    virtual void OnSend(int nErrorCode); // FD_WRITE 觸發
};

CSendSocket m_sock;
CDC m_memDC; CBitmap m_bmp;
CDC* m_pDeskDC;
int m_nFrameIdx = 1000; // 資料指標
short m_pixelBuf[350000]; // 640x480x2 bytes
char m_frameBuf[5000]; // 壓縮後封包

3. 初始化 (OnInitDialog)


m_sock.Create(2001, SOCK_DGRAM, FD_WRITE);
BOOL bOpt = TRUE;
m_sock.SetSockOpt(SO_BROADCAST, &bOpt, sizeof(BOOL));
m_sock.SetSockOpt(SO_DONTROUTE, &bOpt, sizeof(BOOL));
m_sock.SetSockOpt(SO_SNDBUF, &eee, sizeof(int)); // 8192
m_sock.AsyncSelect(FD_WRITE);

CWindowDC ddc(GetDesktopWindow());
m_pDeskDC = &ddc;
m_memDC.CreateCompatibleDC(m_pDeskDC);
m_bmp.CreateCompatibleBitmap(m_pDeskDC, 640, 480);
m_memDC.SelectObject(&m_bmp);

4. OnSend - 壓縮與發送迴圈


void CSendSocket::OnSend(int nErrorCode)
{
    if (m_nFrameIdx > 307200) // 一幀結束
    {
        m_nFrameIdx = 1000;
        m_memDC.BitBlt(0,0,640,480, m_pDeskDC,0,0, SRCCOPY);
        m_bmp.GetBitmapBits(614400, &m_pixelBuf[1000]);

        // 繪製滑鼠游標
        POINT pt; GetCursorPos(&pt);
        for (int y=0; y<10 && pt.y+y<480; y++)
            for (int x=0; x<10 && pt.x+x<640; x++)
                m_pixelBuf[(pt.y+y)*640 + pt.x+x + 1000] = 31744;
    }

    // 簡易 JPEG 壓縮:8 pixel 一組
    char* pf = &m_frameBuf[4];
    short* pfi = (short*)(pf+1);
    int* pa = (int*)m_frameBuf;
    *pa = m_nFrameIdx;

    while (pf < &m_frameBuf[3836])
    {
        *pf = 0;
        for (int i=0; i<8; i+=2)
        {
            short cur = m_pixelBuf[m_nFrameIdx];
            short left = m_pixelBuf[m_nFrameIdx-1];
            short up   = m_pixelBuf[m_nFrameIdx-640];
            short upleft = m_pixelBuf[m_nFrameIdx-641];

            if (cur == left)       *pf |= (0x40 >> i);
            else if (cur == up)    *pf |= (0x80 >> i);
            else if (cur == upleft)*pf |= (0xC0 >> i);
            else { *pfi = cur; pfi++; }
            m_nFrameIdx++;
        }
        pf = (char*)pfi;
        pfi = (short*)(pf+1);
    }

    AsyncSelect(FD_WRITE); // 繼續監聽
    SendTo(m_frameBuf, 3840, 1050, NULL, 0); // 廣播埠 1050
}

學生端 (接收器) 實作

1. 專案建立

  • MFC AppWizard → SDI 專案 Netcc,勾選 Windows Sockets。

2. 核心類別


class CRecvSocket : public CAsyncSocket
{
public:
    virtual void OnReceive(int nErrorCode); // FD_READ 觸發
};

CRecvSocket m_sock;
CDC m_memDC; CBitmap m_bmp;
CDC* m_pViewDC;
short m_pixelBuf[350000];

3. OnReceive - 解壓與顯示


void CRecvSocket::OnReceive(int nErrorCode)
{
    CString strIP; UINT nPort;
    ReceiveFrom(m_frameBuf, 3840, strIP, nPort);

    char* pf = &m_frameBuf[4];
    short* pfi = (short*)(pf+1);
    int* pa = (int*)m_frameBuf;

    while (pf < &m_frameBuf[3836])
    {
        for (int i=0; i<8; i+=2)
        {
            BYTE flag = *pf & (0xC0 >> i);
            if (flag == (0x40 >> i))       m_pixelBuf[*pa] = m_pixelBuf[*pa - 1];
            else if (flag == (0x80 >> i))  m_pixelBuf[*pa] = m_pixelBuf[*pa - 640];
            else if (flag == (0xC0 >> i))  m_pixelBuf[*pa] = m_pixelBuf[*pa - 641];
            else { m_pixelBuf[*pa] = *pfi; pfi++; }
            (*pa)++;
        }
        pf = (char*)pfi;
        pfi = (short*)(pf+1);
    }

    if (*pa > 307200) // 一幀完成
    {
        m_bmp.SetBitmapBits(614400, &m_pixelBuf[1000]);
        m_pViewDC->BitBlt(0,0,640,480, &m_memDC,0,0, SRCCOPY);
    }
}

關鍵技術總結

  • 非同步 UDP:CAsyncSocket + FD_WRITE/FD_READ 事件驅動,不阻塞 UI。
  • 廣播模式:SO_BROADCAST 讓單一封包到達所有學生端。
  • 差分壓縮:利用空間相關性 (左、上、左上) 編碼,大幅縮減封包大小。
  • 雙緩衝顯示:記憶體 DC 合成後一次 BitBlt 至視窗,無閃爍。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved