📄 rmcast.cpp
字号:
fec.FECBlockSize = (USHORT) blocksize;
fec.FECProActivePackets = (USHORT) proactive;
fec.FECGroupSize = (UCHAR) blocksize;
fec.fFECOnDemandParityEnabled = (BOOLEAN)ondemand;
rc = setsockopt(
s,
IPPROTO_RM,
RM_USE_FEC,
(char *)&fec,
sizeof(fec)
);
if (rc == SOCKET_ERROR)
{
printf("Setting FEC parameters:\n");
printf(" Block size: %d\n", blocksize);
printf(" Pro active: %d\n", proactive);
printf(" Group size: %d\n", groupsize);
printf(" On demand : %s\n", (ondemand ? "TRUE" : "FALSE"));
}
else
{
fprintf(stderr, "setsockopt: RM_USE_FEC failed: %d\n", WSAGetLastError());
}
return rc;
}
//
// Function: SetWindowSize
//
// Description:
// This routine sets the window size for the sending socket which includes
// the byte rate, window size, and window time parameters. Before setting
// the parameters a simple calculation is performed to determine whether
// the values passed in make sense. If they don't an error message is
// displayed but the set is attempted anyway. If the values don't jive
// then the option will fail with WSAEINVAL and the default window
// rate, size, and time are used instead.
//
//
int SetWindowSize(SOCKET s, int windowsize, int windowtime, int windowrate)
{
RM_SEND_WINDOW window;
int rc;
memset(&window, 0, sizeof(window));
if (windowsize != ((windowrate/8) * windowtime))
{
printf("Window paramters don't compute!\n");
}
window.RateKbitsPerSec = windowrate;
window.WindowSizeInMSecs = windowtime;
window.WindowSizeInBytes = windowsize;
rc = setsockopt(
s,
IPPROTO_RM,
RM_RATE_WINDOW_SIZE,
(char *)&window,
sizeof(window)
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "setsockopt: RM_RATE_WINDOW_SIZE failed: %d\n", WSAGetLastError());
}
else
{
printf("Setting window paramters:\n");
printf(" Rate (kbits/sec): %d\n", windowrate);
printf(" Size (bytes) : %d\n", windowsize);
printf(" Time (msec) : %d\n", windowtime);
}
return rc;
}
//
// Function: SetLateJoin
//
// Description:
// This option sets the latejoin value. This specifies the percentage of the
// window that a receiver can NAK in the event the receiver picked up the
// session in the middle of the sender's transmission. This option is set
// on the sender side and is advertised to the receivers when the session
// is joined.
//
int SetLateJoin(SOCKET s, int latejoin)
{
int rc;
rc = setsockopt(
s,
IPPROTO_RM,
RM_LATEJOIN,
(char *)&latejoin,
sizeof(latejoin)
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "setsockopt: RM_LATEJOIN failed: %d\n", WSAGetLastError());
}
else
{
printf("Setting latejoin: %d\n", latejoin);
}
return rc;
}
//
// Function: main
//
// Description:
// Parse the command line arguments, load the Winsock library,
// create a socket and join the multicast group. If set as a
// sender then begin sending messages to the multicast group;
// otherwise, call recvfrom() to read messages send to the
// group.
//
int _cdecl main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s,
sc;
SOCKADDR_STORAGE remote;
struct addrinfo *resmulti=NULL,
*resif=NULL,
*resbind=NULL;
char *buf=NULL;
int remotelen,
err,
rc,
i=0;
// Parse the command line
ValidateArgs(argc, argv);
// Load Winsock
if (WSAStartup(MAKEWORD(1, 1), &wsd) != 0)
{
printf("WSAStartup failed\n");
return -1;
}
// Resolve the multicast address
resmulti = ResolveAddress(gMulticast, gPort, AF_INET, 0, 0);
if (resmulti == NULL)
{
fprintf(stderr, "Unable to convert multicast address '%s': %d\n",
gMulticast, WSAGetLastError());
return -1;
}
//
// Create the socket. In Winsock 1 you don't need any special
// flags to indicate multicasting.
//
s = socket(resmulti->ai_family, gSocketType, gProtocol);
if (s == INVALID_SOCKET)
{
printf("socket failed with: %d\n", WSAGetLastError());
return -1;
}
printf("socket handle = 0x%p\n", s);
// Allocate the send/receive buffer
buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, gBufferSize);
if (buf == NULL)
{
fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError());
return -1;
}
if (bSender)
{
// Bind to the wildcard address
resbind = ResolveAddress(NULL, gPort, AF_INET, 0, 0);
if (resbind == NULL)
{
fprintf(stderr, "Unable to obtain bind address!\n");
return -1;
}
// Bind the socket
rc = bind(s, resbind->ai_addr, resbind->ai_addrlen);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
return -1;
}
freeaddrinfo(resbind);
// If sepcified, set the send interface
if (gInterfaceCount == 1)
{
resif = ResolveAddress(gListenInterface[0], gPort, AF_INET, 0, 0);
if (resif == NULL)
{
return -1;
}
rc = SetSendInterface(s, resif);
freeaddrinfo(resif);
// Set the TTL to something else. The default TTL is one.
rc = SetMulticastTtl(s, resmulti->ai_family, gTtl);
if (rc == SOCKET_ERROR)
{
return -1;
}
}
// If specified set the late joiner option
if (gLateJoin != -1)
{
SetLateJoin(s, gLateJoin);
}
// If specified set the window paramters
if (bSetSendWindow)
{
SetWindowSize(s, gWindowSizeBytes, gWindowSizeMSec, gWindowRateKbitsSec);
}
// If specified set the FEC paramters
if (bUseFec == TRUE)
{
SetFecParameters(s, gFecBlockSize, gFecGroupSize, bFecOnDemand, gFecProActive);
}
// Connect the socket to the multicast group the session is to be on
rc = connect(s, resmulti->ai_addr, resmulti->ai_addrlen);
if (rc == SOCKET_ERROR)
{
printf("connect failed: %d\n", WSAGetLastError());
return -1;
}
memset(buf, '^', gBufferSize);
// Send some data
for(i=0; i < gCount ; i++)
{
rc = send(
s,
buf,
gBufferSize,
0
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "send failed with: %d\n", WSAGetLastError());
return -1;
}
printf("SENT %d bytes\n", rc);
}
}
else
{
// Bind the socket to the multicast address on which the session will take place
rc = bind(s, resmulti->ai_addr, resmulti->ai_addrlen);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
return -1;
}
printf("Binding to ");
PrintAddress(resmulti->ai_addr, resmulti->ai_addrlen);
printf("\n");
// Add each supplied interface as a receive interface
if (gInterfaceCount > 0)
{
for(i=0; i < gInterfaceCount ;i++)
{
resif = ResolveAddress(gListenInterface[i], "0", AF_INET, 0, 0);
if (resif == NULL)
{
return -1;
}
rc = AddReceiveInterface(s, resif);
freeaddrinfo(resif);
}
}
// Listen for sessions
rc = listen(s, 1);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
return -1;
}
// Wait for a session to become available
remotelen = sizeof(remote);
sc = accept(s, (SOCKADDR *)&remote, &remotelen);
if (sc == INVALID_SOCKET)
{
fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
return -1;
}
printf("Join multicast session from: ");
PrintAddress((SOCKADDR *)&remote, remotelen);
printf("\n");
while (1)
{
// Receive data until an error or until the session is closed
rc = recv(sc, buf, gBufferSize, 0);
if (rc == SOCKET_ERROR)
{
if ((err = WSAGetLastError()) != WSAEDISCON)
{
fprintf(stderr, "recv failed: %d\n", err);
}
break;
}
else
{
printf("received %d bytes\n", rc);
}
}
// Close the session socket
closesocket(sc);
}
// Clean up
freeaddrinfo(resmulti);
closesocket(s);
WSACleanup();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -