网上以及书上很多地方说道可靠多播,看后也明白点,但是很模糊。。。
也看了《 Windows网络编程》对照下,终于实现了。。
服务端部分代码:
// DlgReliableMulticast.cpp : implementation file
//
#include "stdafx.h"
#include "TestServer.h"
#include "DlgReliableMulticast.h"
// CDlgReliableMulticast dialog
IMPLEMENT_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 handlers
BOOL CDlgReliableMulticast::OnInitDialog() {
CDialog::OnInitDialog();
InitNetwork();
return TRUE;
}
void CDlgReliableMulticast::InitNetwork() {
// Create thread
DWORD 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 = ...;// 本机IP
WSADATA 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_ANY
sockaddr_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 dialog
IMPLEMENT_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 handlers
BOOL CDlgReliableMulticast::OnInitDialog() {
CDialog::OnInitDialog();
InitNetwork();
return TRUE;
}
void CDlgReliableMulticast::InitNetwork() {
// Create thread
DWORD 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 = ...; // 本机IP
WSADATA 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;
}