PGM Senders and Receivers
Establishing a PGM session is similar to the connection establishment routine associated with a TCP session. The significant departure from a TCP session, however, is that the client and server semantics are reversed; the server (the PGM sender) connects to a multicast group, while the client (the PGM receiver) waits to accept a connection. The following paragraphs detail programmatic steps necessary for creating a PGM sender and a PGM receiver. This page also describes the available data modes for PGM sessions.
To create a PGM sender, perform the following steps
- Create a PGM socket.
- bind the socket to INADDR_ANY.
- connect to the multicast group transmission address.
No formal session handshaking is performed with any clients. The connection process is similar to a UDP connect, in that it associates an endpoint address (the multicast group) with the socket. Once completed, data may be sent on the socket.
When a sender creates a PGM socket and connects it to a multicast address, a PGM session is created. A reliable multicast session is defined by a combination of the globally unique identifier (GUID) and the source port. The GUID is generated by the transport. The sSource port is specified by the transport, and no control is provided over which source port is used.
The following code snippet illustrates setting up a PGM sender:
SOCKET s; SOCKADDR_IN salocal, sasession; int dwSessionPort; s = socket (AF_INET, SOCK_RDM, IPPROTO_RM); salocal.sin_family = AF_INET; salocal.sin_port = htons (0); // Port is ignored here salocal.sin_addr.s_addr = htonl (INADDR_ANY); bind (s, (SOCKADDR *)&salocal, sizeof(salocal)); // // Set all relevant sender socket options here // // // Now, connect <entity type="hellip"/> // Setting the connection port (dwSessionPort) has relevance, and // can be used to multiplex multiple sessions to the same // multicast group address over different ports // dwSessionPort = 0; sasession.sin_family = AF_INET; sasession.sin_port = htons (dwSessionPort); sasession.sin_addr.s_addr = inet_addr ("188.8.131.52"); connect (s, (SOCKADDR *)&sasession, sizeof(sasession)); // // We're now ready to send data! //
To create a PGM receiver, perform the following steps
- Create a PGM socket.
- bind the socket to the multicast group address on which the sender is transmitting.
- Call the listen function on the socket to put the socket in listening mode. The listen function returns when a PGM session is detected on the specified multicast group address and port.
- Call the accept function to obtain a new socket handle corresponding to the session.
Only original PGM data (ODATA) triggers the acceptance of a new session. As such, other PGM traffic (such as SPM or RDATA packets) may be received by the transport, but do not result in the listen function returning.
Once a session is accepted, the returned socket handle is used for receiving data.
The following code snippet illustrates setting up a PGM receiver:
SOCKET s, sclient; SOCKADDR_IN salocal, sasession; int sasessionsz, dwSessionPort; s = socket (AF_INET, SOCK_RDM, IPPROTO_RM); // // The bind port (dwSessionPort) specified should match that // which the sender specified in the connect call // dwSessionPort = 0; salocal.sin_family = AF_INET; salocal.sin_port = htons (dwSessionPort); salocal.sin_addr.s_addr = inet_addr ("184.108.40.206"); bind (s, (SOCKADDR *)&salocal, sizeof(salocal)); // // Set all relevant receiver socket options here // listen (s, 10); sasessionsz = sizeof(sasession); sclient = accept (s, (SOCKADDR *)&sasession, &sasessionsz); // // accept will return the client socket and we are now ready // to receive data on the new socket! //
PGM sessions have two options for data modes: message mode and stream mode.
Message mode is appropriate for applications that need to send discrete messages, and is specified by a socket type of SOCK_RDM. Stream mode is appropriate for applications that need to send streaming data to receivers, such as video or voice applications, and is specified by a socket type of SOCK_STREAM. The choice of mode effects how Winsock processes data.
Consider the following example: A message mode PGM sender makes three calls to the WSASend function, each with a 100-byte buffer. This operation appears on the wire as three discrete PGM packets. On the receiver side, each call to the WSARecv function returns only 100 bytes, even if a larger receive buffer is provided. In contrast, with a stream mode PGM sender those three 100 byte transmissions could be coalesced into less than three physical packets on the wire (or coalesced into one blob of data on the receiver side). As such, when the receiver calls one of the Windows Sockets receive functions, any amount of data that has been received by the PGM transport may be returned to the application without regard to how the data was physically transmitted or received.