網上以及書上很多地方說道可靠多播,看後也明白點,但是很模糊。。。
也看了《 Windows網路編程》對照下,終於實現了。。
服務端部分代碼:
// DlgReliableMulticast.cpp : implementation file//#include "stdafx.h"#include "TestServer.h"#include "DlgReliableMulticast.h"// CDlgReliableMulticast dialogIMPLEMENT_DYNAMIC(CDlgReliableMulticast, CDialog)CDlgReliableMulticast::CDlgReliableMulticast(CWnd* pParent /*=NULL*/): CDialog(CDlgReliableMulticast::IDD, pParent){m_hWorkThread = NULL;}CDlgReliableMulticast::~CDlgReliableMulticast(){}void CDlgReliableMulticast::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CDlgReliableMulticast, CDialog)END_MESSAGE_MAP()// CDlgReliableMulticast message handlersBOOL CDlgReliableMulticast::OnInitDialog() {CDialog::OnInitDialog();InitNetwork();return TRUE;}void CDlgReliableMulticast::InitNetwork() {// Create threadDWORD dwThreadID = 0;m_hWorkThread = CreateThread(NULL, 0, NetworkThreadProc, this, CREATE_SUSPENDED, &dwThreadID);if (NULL == m_hWorkThread) { return; }SetThreadPriority(m_hWorkThread, THREAD_PRIORITY_HIGHEST);ResumeThread(m_hWorkThread);}DWORD WINAPI CDlgReliableMulticast::NetworkThreadProc(LPVOID lpvParam) {CDlgReliableMulticast *pThis = (CDlgReliableMulticast *)lpvParam;return pThis->ThreadProc();}DWORD CDlgReliableMulticast::ThreadProc(){m_dwLocalIpAddr = ...;// 本機IPWSADATA wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);m_hSocket = socket(AF_INET, SOCK_RDM, IPPROTO_RM);if( m_hSocket == INVALID_SOCKET ) {int nErr = WSAGetLastError();LogPrintf(_T("socket: ErrorCode: %d\n"), nErr);}// 綁定到INADDR_ANYsockaddr_in localAddr;memset(&localAddr, 0, sizeof(localAddr));localAddr.sin_family = AF_INET;localAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);localAddr.sin_port = htons(0);int nRet = bind(m_hSocket, (sockaddr*)&localAddr, sizeof(localAddr));if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("bind: ErrorCode: %d\n"), nErr);}// 設定外出介面ULONG ulSend = m_dwLocalIpAddr;nRet = setsockopt(m_hSocket, IPPROTO_RM, RM_SET_SEND_IF, (char*)&ulSend, sizeof(ulSend));if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("setsockopt: ErrorCode: %d\n"), nErr);}// 將通訊端串連到將多播組地址sockaddr_in addrMulti;memset(&addrMulti, 0, sizeof(addrMulti));addrMulti.sin_family = AF_INET;addrMulti.sin_addr.S_un.S_addr = inet_addr("234.5.6.7");addrMulti.sin_port = htons(5150);nRet = connect(m_hSocket, (sockaddr*)&addrMulti, sizeof(addrMulti));if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("setsockopt: ErrorCode: %d\n"), nErr);}char buf[1024]={0};buf[0] = 'a';buf[1] = 'v';buf[2] = 'd';buf[3] = 'r';while(1) {nRet = send(m_hSocket, buf, sizeof(buf), 0);if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("send: ErrorCode: %d\n"), nErr);}}WSACleanup();return 0;}
用戶端:
// DlgReliableMulticast.cpp : implementation file//#include "stdafx.h"#include "TestClient.h"#include "DlgReliableMulticast.h"// CDlgReliableMulticast dialogIMPLEMENT_DYNAMIC(CDlgReliableMulticast, CDialog)CDlgReliableMulticast::CDlgReliableMulticast(CWnd* pParent /*=NULL*/): CDialog(CDlgReliableMulticast::IDD, pParent){m_hWorkThread = NULL;}CDlgReliableMulticast::~CDlgReliableMulticast(){}void CDlgReliableMulticast::DoDataExchange(CDataExchange* pDX){CDialog::DoDataExchange(pDX);}BEGIN_MESSAGE_MAP(CDlgReliableMulticast, CDialog)END_MESSAGE_MAP()// CDlgReliableMulticast message handlersBOOL CDlgReliableMulticast::OnInitDialog() {CDialog::OnInitDialog();InitNetwork();return TRUE;}void CDlgReliableMulticast::InitNetwork() {// Create threadDWORD dwThreadID = 0;m_hWorkThread = CreateThread(NULL, 0, NetworkThreadProc, this, CREATE_SUSPENDED, &dwThreadID);if (NULL == m_hWorkThread) { return; }SetThreadPriority(m_hWorkThread, THREAD_PRIORITY_HIGHEST);ResumeThread(m_hWorkThread);}DWORD WINAPI CDlgReliableMulticast::NetworkThreadProc(LPVOID lpvParam) {CDlgReliableMulticast *pThis = (CDlgReliableMulticast *)lpvParam;return pThis->ThreadProc();}DWORD CDlgReliableMulticast::ThreadProc(){m_dwLocalIpAddr = ...; // 本機IPWSADATA wsaData;WSAStartup(MAKEWORD(2,2), &wsaData);m_hSocket = socket(AF_INET, SOCK_RDM, IPPROTO_RM);if( m_hSocket == INVALID_SOCKET ) {int nErr = WSAGetLastError();LogPrintf(_T("socket: ErrorCode: %d\n"), nErr);}sockaddr_in addrMulti;memset(&addrMulti, 0, sizeof(addrMulti));addrMulti.sin_family = AF_INET;addrMulti.sin_addr.S_un.S_addr = inet_addr("234.5.6.7");addrMulti.sin_port = htons(5150);int nRet = bind(m_hSocket, (sockaddr*)&addrMulti, sizeof(addrMulti));if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("bind: ErrorCode: %d\n"), nErr);}nRet = listen(m_hSocket, 10);if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("listen: ErrorCode: %d\n"), nErr);}ULONG localIpAddress = m_dwLocalIpAddr;nRet = setsockopt(m_hSocket, IPPROTO_RM, RM_ADD_RECEIVE_IF, (char*)&localIpAddress, sizeof(localIpAddress));if( nRet == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("listen: ErrorCode: %d\n"), nErr);}sockaddr_in addrFrom;int fromLen = sizeof(addrFrom);SOCKET ns = accept(m_hSocket, (sockaddr*)&addrFrom, &fromLen);if( ns == INVALID_SOCKET ) {int nErr = WSAGetLastError();LogPrintf(_T("accept: ErrorCode: %d\n"), nErr);}closesocket(m_hSocket);// while(1) {char buf[1024];int rc = recv(ns, buf, sizeof(buf), 0);if( rc == SOCKET_ERROR ) {int nErr = WSAGetLastError();LogPrintf(_T("recv : ErrorCode: %d\n"), nErr);} else {// }}closesocket(ns);WSACleanup();return 0;}
同時你必須在本機安裝可靠多播協議,如下: