mcast.c

来自「GNet是一个简单的网络库。它是目标定向的」· C语言 代码 · 共 343 行

C
343
字号
/* GNet - Networking library * Copyright (C) 2000  David Helder * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA  02111-1307, USA. */#include "gnet-private.h"#include "mcast.h"/** *  gnet_mcast_socket_new: *   *  Create a new multicast socket with any available port.  Use this *  constructor when you are creating a new group and the port number *  doesn't matter.  If you want to receive packets from the group, *  you will have to join it next. * *  Returns: a new #GMcastSocket, or NULL if there was a failure.  * **/GMcastSocket*gnet_mcast_socket_new(void){  GMcastSocket* ms;  ms = gnet_mcast_socket_port_new(0);  return ms;}/** *  gnet_mcast_socket_port_new: *  @port: Port for the #GMcastSocket. * *  Create a new multicast socket with the given port.  If you know *  the port of the group you will join, use this constructor.  If you *  want to receive packets from the group, you will have to join it, *  using the full address, next. * *  Returns: a new #GMcastSocket, or NULL if there was a failure.   * **/GMcastSocket* gnet_mcast_socket_port_new(gint port){  struct sockaddr sa;  struct sockaddr_in* saip;  GInetAddr* ia;  GMcastSocket* ms;  saip = (struct sockaddr_in*) &sa;  saip->sin_family = AF_INET;  saip->sin_addr.s_addr = g_htonl(INADDR_ANY);  saip->sin_port = g_htons(port);  ia = gnet_private_inetaddr_sockaddr_new(sa);  ms = gnet_mcast_socket_inetaddr_new(ia);  gnet_inetaddr_delete(ia);    return ms;}/** *  gnet_mcast_socket_inetaddr_new: *  @ia: #GInetAddr of the multicast group. * *  Create a new multicast socket with the #GInetAddr.  If you know *  the #GInetAddr of the group you will join, use this constructor. *  If you want to receive packets from the group, you will have to *  join it next. * *  Returns: a new #GMcastSocket, or NULL if there was a failure. * **/GMcastSocket* gnet_mcast_socket_inetaddr_new (const GInetAddr* ia){  GMcastSocket* ms;  const int on = 1;  ms = g_new0(GMcastSocket, 1);  /* Create socket */  ms->ref_count = 1;  ms->sockfd = socket(AF_INET, SOCK_DGRAM, 0);  if (ms->sockfd < 0)    return NULL;  /* Copy address */  ms->sa = ia->sa;  /* Set socket option to share the UDP port */  if (setsockopt(ms->sockfd, SOL_SOCKET, SO_REUSEADDR, 		     (void*) &on, sizeof(on)) != 0)    g_warning("Can't reuse mcast socket\n");  /* Bind to the socket to some local address and port */  if (bind(ms->sockfd, &ms->sa, sizeof(ms->sa)) != 0)    return NULL;  return ms;}/** *  gnet_mcast_socket_delete: *  @ms: #GMcastSocket to delete. * *  Close and delete a multicast socket. * **/voidgnet_mcast_socket_delete(GMcastSocket* ms){  if (ms != NULL)    gnet_mcast_socket_unref(ms);}/** *  gnet_mcast_socket_ref *  @s: #GMcastSocket to reference * *  Increment the reference counter of the #GMcastSocket. * **/voidgnet_mcast_socket_ref(GMcastSocket* s){  g_return_if_fail(s != NULL);  ++s->ref_count;}/** *  gnet_mcast_socket_unref *  @s: #GMcastSocket to unreference * *  Remove a reference from the #GMcastSocket.  When reference count *  reaches 0, the socket is deleted. * **/voidgnet_mcast_socket_unref(GMcastSocket* s){  g_return_if_fail(s != NULL);  --s->ref_count;  if (s->ref_count == 0)    {      GNET_CLOSE_SOCKET(s->sockfd);	/* Don't care if this fails... */      if (s->iochannel)	g_io_channel_unref(s->iochannel);      g_free(s);    }}/** *  gnet_mcast_socket_join_group: *  @ms: #GMcastSocket to use. *  @ia: Address of the group. * *  Join the multicast group using the multicast socket.  You should *  only join one group per socket.   * *  Returns: 0 on success. * **/gintgnet_mcast_socket_join_group (GMcastSocket* ms, const GInetAddr* ia){  struct ip_mreq mreq;  /* Create the multicast request structure */  memcpy(&mreq.imr_multiaddr, 	 &((struct sockaddr_in*) &ia->sa)->sin_addr,	 sizeof(struct in_addr));  mreq.imr_interface.s_addr = g_htonl(INADDR_ANY);  /* Join the group */  return setsockopt(ms->sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,		    (void*) &mreq, sizeof(mreq));}/** *  gnet_mcast_socket_leave_group: *  @ms: #GMcastSocket to use. *  @ia: Address of the group to leave. * *  Leave the mulitcast group. * *  Returns: 0 on success. * **/gintgnet_mcast_socket_leave_group (GMcastSocket* ms, const GInetAddr* ia){  struct ip_mreq mreq;  /* Create the multicast request structure */  memcpy(&mreq.imr_multiaddr,	 &((struct sockaddr_in*) &ia->sa)->sin_addr,	 sizeof(struct in_addr));  mreq.imr_interface.s_addr = g_htonl(INADDR_ANY);  /* Leave the group */  return setsockopt(ms->sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,		    (void*) &mreq, sizeof(mreq));}/** *  gnet_mcast_socket_send: *  @ms: #GMcastSocket to use to send. *  @packet: Packet to send. * *  Send the packet using the multicast socket.   * *  Returns: 0 if successful. * **/gint gnet_mcast_socket_send (GMcastSocket* ms, const GUdpPacket* packet){  return gnet_udp_socket_send((GUdpSocket*) ms, packet);}/** *  gnet_mcast_socket_receive: *  @ms: #GMcastSocket to receive from. *  @packet: Packet to receive. * *  Receive a packet using the mcast socket.   * *  Returns: the number of bytes received, -1 if unsuccessful. * **/gint gnet_mcast_socket_receive (GMcastSocket* ms, GUdpPacket* packet){  return gnet_udp_socket_receive((GUdpSocket*) ms, packet);}/** *  gnet_mcast_socket_has_packet: *  @s: #GMcastSocket to check * *  Test if the socket has a receive packet.   * *  Returns: TRUE if there is packet waiting, FALSE otherwise. * **/gbooleangnet_mcast_socket_has_packet (const GMcastSocket* s){  return gnet_udp_socket_has_packet((const GUdpSocket*) s);}/** *  gnet_mcast_socket_is_loopback: *  @ms: #GMcastSocket to check. * *  Check if the multicast socket has loopback enabled.  If loopback *  is enabled, you receive all the packets you send.  Most people *  don't want this. * *  Returns: 0 if loopback is disabled. * **/gintgnet_mcast_socket_is_loopback (const GMcastSocket* ms){  guchar flag;  socklen_t flagSize;  flagSize = sizeof(flag);  if (getsockopt(ms->sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, &flagSize) < 0)    return(-1);  g_assert(flagSize <= sizeof(flag));  return (gint) flag;}/** *  gnet_mcast_socket_set_loopback: *  @ms: #GMcastSocket to use. *  @b: Value to set it to (0 or 1) * *  Turn the loopback on or off.  If loopback is on, when the process *  sends a packet, it will automatically be looped back to the host. *  If it is off, not only will this the process not receive datagrams *  it sends, other processes on the host will not receive its *  packets. * *  Returns: 0 if successful. * **/gintgnet_mcast_socket_set_loopback (GMcastSocket* ms, int b){  guchar flag;  flag = (guchar) b;  return setsockopt(ms->sockfd, IPPROTO_IP, IP_MULTICAST_LOOP,		    &flag, sizeof(flag));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?