我有大约 25 个音频流客户端构建在 i.mx6 arm 平台上,运行 linux 版本 4.3.0-rc2-00019-gbcee19f-dirty #36 SMP Tue Feb 9 15:27:51 EST 2016 armv7l
我发现在阿尔伯塔省的 4g lte(mbr1516)上的两个特定单元上,插座每隔几分钟就会断电一次,而网络上其他基于 Windows 的流媒体客户端则在同一时间段内保持工作。
我确实怀疑 4g 蜂窝防火墙正在干扰这些数据包,但却无法确定到底是什么,也不知道如何深入研究。
18:11:35 至 18:12:06 的整个时间段内,其他外部 IP 均有进出流量。我认为该服务器是 linode 设置,不太可能是服务器端问题。
网络配置是Streaming_Box->4G_LTE_Router->internet->Icecast_Server
补充 1:此客户端流媒体设备可以发送多个流,因此如果我发送两个并排的流,一个开放 http,另一个通过 openvpn,则 http 会中断,而隧道 http 不会。
void * StreamingThread1(void * ptr) {
int a, b, SendCount;
ssize_t BytesSent;
int Burst = 1;
time_t timer, timercomp, OnDelay;
time(&timer);
time(&OnDelay);
unsigned char * RxBuff = malloc(5000);
unsigned char * OutBuff = malloc(65535);
if (RxBuff == NULL || OutBuff == NULL) {
MyLog("StreamThread1 Unable to allocate RxBuff or OutBuff\n");
StartupError(50);
}
Control.StreamConnected1 = 0;
Control.StreamConnectErr = StrmErr_None;
signal(SIGPIPE, SIG_IGN);
int sockfd = -1;
struct hostent *server;
struct sockaddr_in serv_addr;
struct timeval tv;
int BuffSize = 65535;
socklen_t optlen = 4;
tv.tv_sec = 10;
tv.tv_usec = 0;
while (1) {
usleep(10000); //Give threads a breather
if (Control.RestartStream1) {
time(&timer);
Control.RestartStream1 = 0;
if (sockfd > -1) {
close(sockfd);
sockfd = -1;
}
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == -1) {
Debug("Unable to create socket %s\n", strerror(errno));
goto ExitConnect;
}
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof (struct timeval));
setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof (struct timeval));
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &BuffSize, optlen);
Burst = 1;
server = gethostbyname((char*) StreamParams.URL1);
if (server == NULL) {
Debug("Error finding host %s\n", StreamParams.URL1);
Control.StreamConnectErr = StrmErr_NoHost;
} else {
bzero((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *) server->h_addr, (char *) &serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(StreamParams.Port1);
Control.StreamConnected1 = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) != -1;
if (!Control.StreamConnected1) {
Debug("ERROR, unable to connect to %s : %i : %i\n", StreamParams.URL1, StreamParams.Port1, errno);
Control.StreamConnectErr = StrmErr_NoConnect;
goto ExitConnect;
} else {
Debug("Connected to %s : %i\n", StreamParams.URL1, StreamParams.Port1);
}
unsigned char* Message = BuildLogin(0);
Control.StreamConnected1 = sendto(sockfd, Message, strlen(Message), MSG_NOSIGNAL, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) > -1;
if (!Control.StreamConnected1) {
Debug("ERROR, unable to write message to %s : %i\n", StreamParams.URL1, StreamParams.Port1);
free(Message);
Control.StreamConnectErr = StrmErr_NoWrite;
goto ExitConnect;
} else {
Debug("Login information sent to %s : %i\n", StreamParams.URL1, StreamParams.Port1);
free(Message);
}
a = recv_catch_eintr(sockfd, RxBuff, 5000, MSG_NOSIGNAL, 10000);
if (a <= 0) {
Control.StreamConnected1 = 0;
Debug("Unable to authenticate, nothing received %s\n", strerror(errno));
} else {
if (strstr((const unsigned char*) RxBuff, "HTTP/1.0 200 OK") != NULL) {
Debug("Authentication successfull\n");
Control.AuthError1 = 0;
} else {
Control.StreamConnected1 = 0;
Control.AuthError1 = 1;
Control.StreamConnectErr = StrmErr_Auth;
Debug("Authentication Error\n");
}
}
}
}
ExitConnect:
if (Control.StreamConnected1 && sockfd > -1) {
if (Burst) {
b = LameParams.BitRate * 3 * 1000 / 8;
if (b > AudioBuffSize - 1024) {
b = AudioBuffSize - 1024;
}
unsigned short Diff = AudioHeadPtr - AudioTailPtr1;
if (Diff > b) {
Burst = 0;
for (a = 0; a < b; a++) {
OutBuff[a] = AudioBuffer[AudioTailPtr1++];
}
Control.StreamConnected1 = send(sockfd, OutBuff, b, 0) == b;
Debug("Sent %i Burst\n", b);
}
} else {
SendCount = 0;
while (AudioTailPtr1 != AudioHeadPtr && a < sizeof (AudioBuffer) - 1024) {
OutBuff[SendCount++] = AudioBuffer[AudioTailPtr1++];
}
if (SendCount > 0 && sockfd > -1) {
BytesSent = send(sockfd, OutBuff, SendCount, MSG_NOSIGNAL);
Control.StreamConnected1 = (BytesSent > 0);
Control.StreamConnectErr = StrmErr_None;
if (BytesSent != SendCount) {
Debug("Tried %i sent %i\n", SendCount, BytesSent);
AudioTailPtr1 -= (SendCount - BytesSent);
}
if (BytesSent < 0) {
AudioTailPtr1 -= SendCount;
Debug("Lost Connection errno %s\n", strerror(errno));
Control.StreamConnectErr = StrmErr_LostConn;
Control.StreamConnected1 = 0;
close(sockfd);
sockfd = -1;
}
}
}
} else {
//Wait 5 then try again.
if (sockfd > -1) {
Debug("Closing socket %i\n", sockfd);
close(sockfd);
sockfd = -1;
}
time(&timercomp);
if (timercomp - timer >= 5) {
Control.RestartStream1 = 1;
Debug("Stream restart at %i\n", timercomp);
}
}
}
}