WinSock programming Multicast

Source: Internet
Author: User

The initial purpose of the packet broadcast method is to discover resources and reduce the amount of data interaction. But in fact, because of packet broadcasting, all hosts in the same network segment must complete data processing whether they are involved in broadcast applications or not. The broadcast UDP packets are processed layer by the system protocol stack of the host until the transport layer delivers them to the application process listening to the corresponding port or discards them. Therefore, frequent broadcast of large data volumes will seriously affect the normal operation of other hosts on the network. The multicast method, while having the advantages of broadcasting, solves this problem well.

Next we will start our multicasting programming Journey:

The first is a simple multicast library. When used, add the header file of this multicast library to your source code.

// File mcastlib. h
# Ifndef _ mcastlib_h _
# DEFINE _ mcastlib_h _

# Include <winsock2.h>
# Include <ws2tcpip. h>

# Ifdef _ cplusplus
Extern "C "{
# Endif
Int mc_join (socket S, struct in_addr * mcaddr, struct in_addr * local_if );
Int mc_setif (socket S, const DWORD local_out_if );
Int mc_getif (socket S, DWORD * local_out_if );
Int mc_setttl (socket S, const dword ttl );
Int mc_getttl (socket S, DWORD * TTL );
Int mc_setloop (socket S, const bool flag );
Int mc_getloop (socket S, bool * flag );
Int mc_leave (socket S, struct in_addr * mcaddr, struct in_addr * local_if );
# Ifdef _ cplusplus
}
# Endif

# Endif

The implementation of this library is as follows:

// File mcastlib. cpp
# Include "mcastlib. H"

// Add the local interface local_if to multicast group mcaddr
Int mc_join (socket S, struct in_addr * mcaddr, struct in_addr * local_if)
{
Struct ip_mreq mreq;
Memcpy (& (mreq. imr_interface), local_if, sizeof (struct in_addr); // local if
Memcpy (& (mreq. imr_multiaddr), mcaddr, sizeof (struct in_addr); // mutilcast group address
Return (setsockopt (S, ipproto_ip, ip_add_membership, (char *) & mreq, sizeof (mreq )));
}

// Set an out-of-office interface for multiple broadcasts
Int mc_setif (socket S, const DWORD local_out_if)
{
Return (setsockopt (S, ipproto_ip, ip_multicast_if, (char *) & local_out_if,
Sizeof (local_out_if )));
}

// Out-of-office interface for obtaining multi-broadcast texts
Int mc_getif (socket S, DWORD * local_out_if)
{
Int Len = sizeof (DWORD );
Return (getsockopt (S, ipproto_ip, ip_multicast_if, (char *) & local_out_if, & Len ));
}

// Set the TTL value of the out-of-the-box multicast message. The default value is 1.
Int mc_setttl (socket S, const dword ttl)
{
Return (setsockopt (S, ipproto_ip, ip_multicast_ttl, (char *) & TTL, sizeof (TTL )));
}

// Obtain the TTL value of the outgoing multicast packets
Int mc_getttl (socket S, DWORD * TTL)
{
Int Len = sizeof (DWORD );
Return (getsockopt (S, ipproto_ip, ip_multicast_ttl, (char *) TTL, & Len ));
}

// Enable or disable loop playback
Int mc_setloop (socket S, const bool flag)
{
Return (setsockopt (S, ipproto_ip, ip_multicast_loop, (char *) & flag, sizeof (FLAG )));
}

// Obtain the local multicast loop status
Int mc_getloop (socket S, bool * flag)
{
Int Len = sizeof (bool );
Return (getsockopt (S, ipproto_ip, ip_multicast_loop, (char *) Flag, & Len ));
}

// The Local interface local_if leaves the multicast group
Int mc_leave (socket S, struct in_addr * mcaddr, struct in_addr * local_if)
{
Struct ip_mreq mreq;
Memcpy (& (mreq. imr_interface), local_if, sizeof (struct in_addr); // local if
Memcpy (& (mreq. imr_multiaddr), local_if, sizeof (struct in_addr); // mutilcast group address
 
Return (setsockopt (S, ipproto_ip, ip_drop_membership, (char *) & mreq, sizeof (mreq )));
}

Next, we will use this multicast library to write the receiver program first. Of course, you can also modify the code so that it can send data.

# Pragma comment (Lib, "ws2_32.lib ")
# Include <stdio. h>
# Include "mcastlib. H"

Int main ()
{
// Init the Winsock enviorment
Wsadata;
Wsastartup (winsock_version, & wsadata );
// Create a socket
Socket sock = socket (af_inet, sock_dgram, 0 );

// Local IP Address
Struct sockaddr_in local;
Memset (& Local, 0, sizeof (local ));
Local. sin_family = af_inet;
Local. sin_port = htons (9999 );
Local. sin_addr.s_un.s_addr = inet_addr ("59.74.17.93 ");

// Bind socket (59.74.17.93, 9999)
If (BIND (sock, (sockaddr *) & Local, sizeof (local) = socket_error ){
Printf ("BIND: % d/N", wsagetlasterror ());
}

// Multicast group address
Struct in_addr mcaddr;
Mcaddr. s_un.s_addr = inet_addr ("233.0.0.1 ");
// Add 59.74.19.52 to the multicast group <233.0.0.1, 9999>
If (mc_join (sock, & mcaddr, & (local. sin_addr) = socket_error ){
Printf ("Join multicast group: % d/N", wsagetlasterror ());
}

// Receive data, consider which Destination Address UDP packets can be received at this time
Char Buf [65];
While (1 ){
Memset (BUF, 0, 65 );
If (recvfrom (sock, Buf, 64, 0, null, null) = socket_error ){
Printf ("recvfrom: % d", wsagetlasterror ());
Break;
}
Else
Printf ("recvd: % s/n", Buf );
If (strcmp (BUF, "quit") = 0)
Break;
}
Return 0;
}

Then, we can start writing the sender program. Of course, it would be better if you are interested to integrate the sender and receiver together.

# Pragma comment (Lib, "ws2_32.lib ")

# Include <stdio. h>
# Include <winsock2.h>
# Include "mcastlib. H"

Void handleerror (char * func );

Int main ()
{
Wsadata;
Wsastartup (winsock_version, & wsadata );

Struct sockaddr_in local;
Memset (& Local, 0, sizeof (local ));
Local. sin_addr.s_un.s_addr = inet_addr ("59.74.19.52 ");
Local. sin_family = af_inet;
Local. sin_port = 9999;

Socket sock = socket (af_inet, sock_dgram, 0 );
// Obtain the default multi-broadcast TTL value and the loop status
Dword ttl;
If (mc_getttl (sock, & TTL) = socket_error ){
Printf ("mc_getttl: % d/N", wsagetlasterror ());
}
Bool loop;
If (mc_getloop (sock, & Loop) = socket_error ){
Printf ("mc_getloop: % d/N", wsagetlasterror ());
}
Printf ("Multicast default: TTL = % d, loopback = % d/N", TTL, loop );

// Set the TTL value to 219.
TTL = 219;
If (mc_setttl (sock, TTL) = socket_error ){
Printf ("mc_setttl: % d/N", wsagetlasterror ());
}

// Send data to multicast groups
Struct sockaddr_in;
Memset (& to, 0, sizeof ());
To. sin_addr.s_un.s_addr = inet_addr ("233.0.0.1 ");
To. sin_family = af_inet;
To. sin_port = htons (9999 );

/* If (mc_join (sock, & mcaddr, & (local. sin_addr )))
{
Handleerror ("mc_join ");
}*/

Char Buf [60];
While (1)
{
Printf ("input:/N ");
Gets (BUF );
Buf [strlen (BUF)] = '/0 ';
Int res = sendto (sock, Buf, strlen (BUF) + 1, 0, (struct sockaddr *) & to, sizeof ());
If (RES = socket_error)
{
Handleerror ("sendto ");
}
Else
Printf ("send out % d bytes! /N ", Res );
If (strcmp (BUF, "quit") = 0)
Break;
}
 
Return 0;
}

Void handleerror (char * func)
{
Int errcode = wsagetlasterror ();

Char info [65] = {0 };
_ Snprintf (Info, 64, "% s: % d/N", func, errcode );
Printf (Info );
}

What to do next? Of course it was a test.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.