⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 groupsockhelper.cpp

📁 流媒体传输协议的实现代码,非常有用.可以支持rtsp mms等流媒体传输协议
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**********This library is free software; you can redistribute it and/or modify it underthe terms of the GNU Lesser General Public License as published by theFree Software Foundation; either version 2.1 of the License, or (at youroption) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)This library is distributed in the hope that it will be useful, but WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESSFOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License formore details.You should have received a copy of the GNU Lesser General Public Licensealong with this library; if not, write to the Free Software Foundation, Inc.,59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**********/// "mTunnel" multicast access service// Copyright (c) 1996-2004 Live Networks, Inc.  All rights reserved.// Helper routines to implement 'group sockets'// Implementation#include "GroupsockHelper.hh"#if defined(__WIN32__) || defined(_WIN32)#include <time.h>extern "C" int initializeWinsockIfNecessary();#else#include <stdarg.h>#include <time.h>#include <fcntl.h>#define initializeWinsockIfNecessary() 1#endif#include <stdio.h>// By default, use INADDR_ANY for the sending and receiving interfaces:netAddressBits SendingInterfaceAddr = INADDR_ANY;netAddressBits ReceivingInterfaceAddr = INADDR_ANY;static void socketErr(UsageEnvironment& env, char* errorMsg) {	env.setResultErrMsg(errorMsg);}int setupDatagramSocket(UsageEnvironment& env, Port port,#ifdef IP_MULTICAST_LOOP			Boolean setLoopback#else			Boolean#endif) {  if (!initializeWinsockIfNecessary()) {    socketErr(env, "Failed to initialize 'winsock': ");    return -1;  }    int newSocket = socket(AF_INET, SOCK_DGRAM, 0);  if (newSocket < 0) {    socketErr(env, "unable to create datagram socket: ");    return newSocket;  }    const int reuseFlag = 1;  if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,		 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {    socketErr(env, "setsockopt(SO_REUSEADDR) error: ");    closeSocket(newSocket);    return -1;  }  #if defined(__WIN32__) || defined(_WIN32)  // Windoze doesn't handle SO_REUSEPORT or IP_MULTICAST_LOOP#else#ifdef SO_REUSEPORT  if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,		 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {    socketErr(env, "setsockopt(SO_REUSEPORT) error: ");    closeSocket(newSocket);    return -1;  }#endif  #ifdef IP_MULTICAST_LOOP  const u_int8_t loop = (u_int8_t)setLoopback;  if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP,		 (const char*)&loop, sizeof loop) < 0) {    socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: ");    closeSocket(newSocket);    return -1;  }#endif#endif    // Note: Windoze requires binding, even if the port number is 0#if defined(__WIN32__) || defined(_WIN32)#else  if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {#endif    struct sockaddr_in name;    name.sin_family = AF_INET;    name.sin_port = port.num();    name.sin_addr.s_addr = ReceivingInterfaceAddr;    if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {      char tmpBuffer[100];      sprintf(tmpBuffer, "bind() error (port number: %d): ",	      ntohs(port.num()));      socketErr(env, tmpBuffer);      closeSocket(newSocket);      return -1;    }#if defined(__WIN32__) || defined(_WIN32)#else  }#endif    // Set the sending interface for multicasts, if it's not the default:  if (SendingInterfaceAddr != INADDR_ANY) {    struct in_addr addr;    addr.s_addr = SendingInterfaceAddr;        if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,		   (const char*)&addr, sizeof addr) < 0) {      socketErr(env, "error setting outgoing multicast interface: ");      closeSocket(newSocket);      return -1;    }  }    return newSocket;}int setupStreamSocket(UsageEnvironment& env,                      Port port, Boolean makeNonBlocking) {  if (!initializeWinsockIfNecessary()) {    socketErr(env, "Failed to initialize 'winsock': ");    return -1;  }    int newSocket = socket(AF_INET, SOCK_STREAM, 0);  if (newSocket < 0) {    socketErr(env, "unable to create stream socket: ");    return newSocket;  }    const int reuseFlag = 1;  if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,		 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {    socketErr(env, "setsockopt(SO_REUSEADDR) error: ");    closeSocket(newSocket);    return -1;  }    // SO_REUSEPORT doesn't really make sense for TCP sockets, so we  // normally don't set them.  However, if you really want to do this  // #define REUSE_FOR_TCP#ifdef REUSE_FOR_TCP#if defined(__WIN32__) || defined(_WIN32)    // Windoze doesn't handle SO_REUSEPORT#else#ifdef SO_REUSEPORT  if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,		 (const char*)&reuseFlag, sizeof reuseFlag) < 0) {    socketErr(env, "setsockopt(SO_REUSEPORT) error: ");    closeSocket(newSocket);    return -1;  }#endif#endif#endif  // Note: Windoze requires binding, even if the port number is 0#if defined(__WIN32__) || defined(_WIN32)#else  if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {#endif    struct sockaddr_in name;    name.sin_family = AF_INET;    name.sin_port = port.num();    name.sin_addr.s_addr = ReceivingInterfaceAddr;    if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {      char tmpBuffer[100];      sprintf(tmpBuffer, "bind() error (port number: %d): ",	      ntohs(port.num()));      socketErr(env, tmpBuffer);      closeSocket(newSocket);      return -1;    }#if defined(__WIN32__) || defined(_WIN32)#else  }#endif  if (makeNonBlocking) {    // Make the socket non-blocking:#if defined(__WIN32__) || defined(_WIN32) || defined(IMN_PIM)    unsigned long arg = 1;    if (ioctlsocket(newSocket, FIONBIO, &arg) != 0) {#elif defined(VXWORKS)    int arg = 1;    if (ioctl(newSocket, FIONBIO, (int)&arg) != 0) {#else    int curFlags = fcntl(newSocket, F_GETFL, 0);    if (fcntl(newSocket, F_SETFL, curFlags|O_NONBLOCK) < 0) {#endif      socketErr(env, "failed to make non-blocking: ");      closeSocket(newSocket);      return -1;    }  }  return newSocket;}#ifndef IMN_PIMstatic int blockUntilReadable(UsageEnvironment& env,			      int socket, struct timeval* timeout) {  int result = -1;  do {    fd_set rd_set;    FD_ZERO(&rd_set);    if (socket < 0) break;    FD_SET((unsigned) socket, &rd_set);    const unsigned numFds = socket+1;        result = select(numFds, &rd_set, NULL, NULL, timeout);    if (timeout != NULL && result == 0) {      break; // this is OK - timeout occurred    } else if (result <= 0) {      socketErr(env, "select() error: ");      break;    }        if (!FD_ISSET(socket, &rd_set)) {      socketErr(env, "select() error - !FD_ISSET");      break;    }  } while (0);  return result;}#elseextern int blockUntilReadable(UsageEnvironment& env,			      int socket, struct timeval* timeout);#endifint readSocket(UsageEnvironment& env,	       int socket, unsigned char* buffer, unsigned bufferSize,	       struct sockaddr_in& fromAddress,	       struct timeval* timeout) {  int bytesRead = -1;  do {    int result = blockUntilReadable(env, socket, timeout);    if (timeout != NULL && result == 0) {      bytesRead = 0;      break;    } else if (result <= 0) {      break;    }        SOCKLEN_T addressSize = sizeof fromAddress;    bytesRead = recvfrom(socket, (char*)buffer, bufferSize, 0,			 (struct sockaddr*)&fromAddress,			 &addressSize);    if (bytesRead < 0) {      //##### HACK to work around bugs in Linux and Windows:      int err = env.getErrno();      if (err == 111 /*ECONNREFUSED (Linux)*/#if defined(__WIN32__) || defined(_WIN32)	  // What a piece of crap Windows is.  Sometimes	  // recvfrom() returns -1, but with an 'errno' of 0.	  // This appears not to be a real error; just treat	  // it as if it were a read of zero bytes, and hope	  // we don't have to do anything else to 'reset'	  // this alleged error:	  || err == 0#else	  || err == EAGAIN#endif	  || err == 113 /*EHOSTUNREACH (Linux)*/) {			        //Why does Linux return this for datagram sock?	fromAddress.sin_addr.s_addr = 0;	return 0;      }      //##### END HACK      socketErr(env, "recvfrom() error: ");      break;    }  } while (0);    return bytesRead;}int readSocketExact(UsageEnvironment& env,		    int socket, unsigned char* buffer, unsigned bufferSize,		    struct sockaddr_in& fromAddress,		    struct timeval* timeout) {  /* read EXACTLY bufferSize bytes from the socket into the buffer.     fromaddress is address of last read.     return the number of bytes acually read when an error occurs  */  int bsize = bufferSize;  int bytesRead = 0;  int totBytesRead =0;  do {    bytesRead = readSocket (env, socket, buffer + totBytesRead, bsize,                            fromAddress, timeout);    if (bytesRead <= 0) break;    totBytesRead += bytesRead;    bsize -= bytesRead;  } while (bsize != 0);  return totBytesRead;}Boolean writeSocket(UsageEnvironment& env,		    int socket, struct in_addr address, Port port,		    u_int8_t ttlArg,		    unsigned char* buffer, unsigned bufferSize) {	do {		if (ttlArg != 0) {			// Before sending, set the socket's TTL:#if defined(__WIN32__) || defined(_WIN32)#define TTL_TYPE int#else#define TTL_TYPE u_int8_t#endif			TTL_TYPE ttl = (TTL_TYPE)ttlArg;			if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,				       (const char*)&ttl, sizeof ttl) < 0) {				socketErr(env, "setsockopt(IP_MULTICAST_TTL) error: ");				break;			}		}		struct sockaddr_in dest;    		dest.sin_family = AF_INET;		dest.sin_port = port.num();		dest.sin_addr = address;		int bytesSent = sendto(socket, (char*)buffer, bufferSize, 0,			               (struct sockaddr*)&dest, sizeof dest);		if (bytesSent != (int)bufferSize) {			char tmpBuf[100];			sprintf(tmpBuf, "writeSocket(%d), sendTo() error: wrote %d bytes instead of %u: ", socket, bytesSent, bufferSize);			socketErr(env, tmpBuf);			break;		}		return True;	} while (0);	return False;}static unsigned getBufferSize(UsageEnvironment& env, int bufOptName,			      int socket) {  unsigned curSize;  SOCKLEN_T sizeSize = sizeof curSize;  if (getsockopt(socket, SOL_SOCKET, bufOptName,		 (char*)&curSize, &sizeSize) < 0) {    socketErr(env, "getBufferSize() error: ");    return 0;  }  return curSize;}unsigned getSendBufferSize(UsageEnvironment& env, int socket) {  return getBufferSize(env, SO_SNDBUF, socket);}unsigned getReceiveBufferSize(UsageEnvironment& env, int socket) {

⌨️ 快捷键说明

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