監聽執行緒 _ListenTcpThread 建立 Socket → Listen → Accept 接受連線 → 接收旗標判斷訊息/檔案/螢幕擷取 → 遞迴重啟監聽執行緒。關閉時透過連接 127.0.0.1 發送結束旗標 'D' 觸發執行緒退出:
UINT _ListenTcpThread(LPVOID lparam)
{
CMyQQDlg* pDlg = (CMyQQDlg*)lparam;
CSocket sockSrvr, recSo;
SOCKADDR_IN client; int iAddrSize = sizeof(client);
sockSrvr.Create(pDlg->m_Port);
sockSrvr.Listen();
sockSrvr.Accept(recSo, (SOCKADDR*)&client, &iAddrSize);
sockSrvr.Close(); // 主監聽 Socket 關閉,交由 recSo 處理
char flag[2]; recSo.Receive(flag, 2);
pDlg->m_type = flag[0];
if (pDlg->m_type == 'D') return 0; // 收到關閉指令
pDlg->pThreadListen = AfxBeginThread(_ListenTcpThread, pDlg); // 重啟監聽
pDlg->ReceiveFileMsg(recSo, client); // 處理檔案/訊息
return 0;
}
// 關閉邏輯
if (m_nSockType == SOCK_TCP && pThreadListen)
{
DWORD dwStatus;
GetExitCodeThread(pThreadListen->m_hThread, &dwStatus);
if (dwStatus == STILL_ACTIVE)
{
CSocket sockClient; sockClient.Create();
sockClient.Connect("127.0.0.1", m_Port);
sockClient.Send("D", 2); // 發送終止旗標
sockClient.Close();
}
}
// 發送端
while (true) {
UINT nRead = myFile.Read(buf, SIZE_FILE);
if (nRead == 0) break;
sockClient.Send(buf, nRead);
}
// 接收端
while (true) {
int nRecv = recSo.Receive(buf, SIZE_FILE);
if (nRecv == 0) break;
file.Write(buf, nRecv);
}
else if (m_type == 'M') {
char buff[100]; CString msg;
while (recSo.Receive(buff, 100) > 0) msg += buff;
CString ip = inet_ntoa(client.sin_addr);
AddMsgList(ip + "<- " + GetNameByIp(ip), msg);
}
採用標準 GDI 方案:GetDC(NULL) → CreateCompatibleDC → BitBlt → GetDIBits 存為 BMP。VC 知識庫範例眾多,此處不贅述。
VC6 + Windows 2000 測試通過。原始碼含完整 UI 與錯誤處理邏輯。