請移步https://higoge.github.io/,全部下載資料在那個博客都能找到。謝謝。 node
--------------------------------------------------------------------git
從這篇博客開始,Jeremiah將會把本身日常寫的些簡單的小程序或者日常讀的開源代碼中比較好的作法和應用整理下來。
github
本篇博客主要是摳取自live555MediaServer,在開啓live555MediaServer的時候會讀取本地IP,而後與rtsp://和文件名組成點播地址。live555MediaServer讀取本地IP的主要方法是:發送一個TTL=0的組播包,接收這個包,而後解析發送地址,即爲本機地址。小程序
這種方法只能得到本機的最主要的IP地址(eth0)。不能獲取全部的IP地址。socket
摳取代碼以下,操做平臺爲RedHat Linux ES5,gcc 4.1.2。ide
/******************************************************************************* * Filename: get_ip.c * Created on: Feb 8, 2010 * Author: Jeremiah * Description: 獲取本機IP地址 * ******************************************************************************/ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <sys/time.h> #include <sys/select.h> in_addr_t ourIPAddress(); int setupDatagramSocket(uint16_t); uint8_t socketJoinGroup(int socket, uint32_t groupAddress); uint8_t writeSocket(int socket, struct in_addr address, uint32_t port, uint8_t ttlArg, unsigned char *buffer, unsigned bufferSize); int readSocket(int socket, unsigned char *buffer, unsigned bufferSize, struct sockaddr_in *fromAddress, struct timeval *timeout); int blockUntilReadable(int socket, struct timeval* timeout); uint8_t badAddress(uint32_t addr); uint8_t socketLeaveGroup(int socket, uint32_t groupAddress); uint8_t IsMulticastAddress(uint32_t address); #define SET_SOCKADDR_SIN_LEN(var) #define MAKE_SOCKADDR_IN(var,adr,prt) /*adr,prt must be in network order*/\ struct sockaddr_in var;\ var.sin_family = AF_INET;\ var.sin_addr.s_addr = (adr);\ var.sin_port = (prt);\ SET_SOCKADDR_SIN_LEN(var); int main(int argc, char **argv) { struct sockaddr_in ourAddress; ourAddress.sin_addr.s_addr = ourIPAddress(); if (ourAddress.sin_addr.s_addr == 0) { printf("get local ip error!\n"); return 1; } printf("%s\n", inet_ntoa(ourAddress.sin_addr)); return 0; } in_addr_t ourIPAddress() { uint32_t ourAddress = 0; int sock = -1; struct in_addr testAddr; struct sockaddr_in fromAddr; fromAddr.sin_addr.s_addr = 0; // Get our address by sending a (0-TTL) multicast packet, // receiving it, and looking at the source address used. // (This is kinda bogus, but it provides the best guarantee // that other nodes will think our address is the same as we do.) testAddr.s_addr = inet_addr("228.67.43.92"); uint16_t testPort = 15948; sock = setupDatagramSocket(testPort); if (sock < 0) { return 0; } if (!socketJoinGroup(sock, testAddr.s_addr)) { return 0; } unsigned char testString[] = "hostIdTest"; unsigned testStrLength = sizeof(testString); if (!writeSocket(sock, testAddr, testPort, 0, testString, testStrLength)) { return 0; } unsigned char readBuffer[20]; struct timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; int bytesRead = readSocket(sock, readBuffer, sizeof(readBuffer), &fromAddr, &timeout); if (bytesRead == 0 // timeout occurred || bytesRead != (int) testStrLength || strncmp( (char *) readBuffer, (char *) testString, testStrLength) != 0) { printf("read socket error\n"); return 0; } uint32_t from = fromAddr.sin_addr.s_addr; if (badAddress(from)) { printf("This computer has an invalid IP address: 0x%x\n", (uint32_t) (ntohl(from))); from = 0; } ourAddress = from; if (sock >= 0) { socketLeaveGroup(sock, testAddr.s_addr); close(sock); } return ourAddress; } int setupDatagramSocket(uint16_t port) { int reuseFlag = 1; int newSocket = socket(AF_INET, SOCK_DGRAM, 0); const uint8_t loop = 1; if (newSocket < 0) { printf("unable to create datagram socket\n"); return newSocket; } if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag, sizeof(reuseFlag)) < 0) { printf("setsockopt(SO_REUSEADDR) error!\n"); close(newSocket); return -1; } if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*) &loop, sizeof(loop)) < 0) { printf("setsockopt(IP_MULTICAST_LOOP) error!\n"); close(newSocket); return -1; } uint32_t addr = INADDR_ANY; MAKE_SOCKADDR_IN(name, addr, port); if (bind(newSocket, (struct sockaddr *) &name, sizeof(name)) != 0) { printf("bind() error (port number: %d)!\n", ntohs(port)); close(newSocket); return -1; } return newSocket; } uint8_t socketJoinGroup(int socket, uint32_t groupAddress) { if (!IsMulticastAddress(groupAddress)) { return 1; // ignore this case } struct ip_mreq imr; imr.imr_multiaddr.s_addr = groupAddress; imr.imr_interface.s_addr = INADDR_ANY; if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *) &imr, sizeof(struct ip_mreq)) < 0) { printf("setsockopt(IP_ADD_MEMBERSHIP) error!\n"); return 0; } return 1; } uint8_t writeSocket(int socket, struct in_addr address, uint32_t port, uint8_t ttlArg, unsigned char *buffer, unsigned bufferSize) { if (ttlArg != 0) { // Before sending, set the socket's TTL: uint8_t ttl = ttlArg; if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) &ttl, sizeof(ttl)) < 0) { printf("setsockopt(IP_MULTICAST_TTL) error!"); return 0; } } MAKE_SOCKADDR_IN(dest, address.s_addr, port); int bytesSent = sendto(socket, (char *) buffer, bufferSize, 0, (struct sockaddr *) &dest, sizeof(dest)); if (bytesSent != (int) bufferSize) { printf("writeSocket(%d), sendTo() error: wrote " "%d bytes instead of %u!\n", socket, bytesSent, bufferSize); return 0; } return 1; } int readSocket(int socket, unsigned char *buffer, unsigned int bufferSize, struct sockaddr_in *fromAddress, struct timeval *timeout) { int bytesRead = -1; int result = blockUntilReadable(socket, timeout); if (timeout != NULL && result == 0) { bytesRead = 0; return -1; } else if (result <= 0) { return -1; } socklen_t addressSize = (socklen_t) sizeof(struct sockaddr_in); bytesRead = recvfrom(socket, (char *) buffer, bufferSize, 0, (struct sockaddr *) fromAddress, &addressSize); if (bytesRead < 0) { printf("recvfrom() error!\n"); return -1; } return bytesRead; } int blockUntilReadable(int socket, struct timeval *timeout) { int result = -1; fd_set rd_set; FD_ZERO(&rd_set); if (socket < 0) return -1; FD_SET((unsigned) socket, &rd_set); const unsigned numFds = socket + 1; result = select(numFds, &rd_set, NULL, NULL, timeout); if (timeout != NULL && result == 0) { printf("select timeout!\n"); return -1; // this is OK - timeout occurred } else if (result <= 0) { printf("select() error!\n"); return -1; } if (!FD_ISSET(socket, &rd_set)) { printf("select() error - !FD_ISSET!\n"); return -1; } return result; } uint8_t badAddress(uint32_t addr) { // Check for some possible erroneous addresses: uint32_t hAddr = ntohl(addr); return (hAddr == 0x7F000001 /* 127.0.0.1 */ || hAddr == 0 || hAddr == (uint32_t) (~0)); } uint8_t socketLeaveGroup(int socket, uint32_t groupAddress) { if (!IsMulticastAddress(groupAddress)) return 1; // ignore this case struct ip_mreq imr; imr.imr_multiaddr.s_addr = groupAddress; imr.imr_interface.s_addr = INADDR_ANY; if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char *) &imr, sizeof(struct ip_mreq)) < 0) { return 0; } return 1; } uint8_t IsMulticastAddress(uint32_t address) { // Note: We return False for addresses in the range 224.0.0.0 // through 224.0.0.255, because these are non-routable // Note: IPv4-specific ##### uint32_t addressInHostOrder = ntohl(address); return addressInHostOrder > 0xE00000FF && addressInHostOrder <= 0xEFFFFFFF; }