У меня около 25 клиентов потокового аудио, построенных на платформе i.mx6 arm, под управлением Linux версии 4.3.0-rc2-00019-gbcee19f-dirty # 36 SMP Tue 9 февраля 15:27:51 EST 2016 armv7l
Я обнаружил, что на двух конкретных устройствах на 4G LTE (mbr1516) в Альберте сокет умирает примерно каждые пару минут, в то время как другие потоковые клиенты на базе Windows в сети продолжают работать в течение того же периода времени.
Я действительно подозреваю, что брандмауэр 4g-ячеек возится с этими пакетами, но не могу понять это и не знаю, куда детализировать.
Существует входящий и исходящий трафик в течение всего периода с 18:11:35 по 18:12:06 на другие внешние IP-адреса. Я думаю, что сервер представляет собой установку линода, маловероятно, что это проблема на стороне сервера.
Конфигурация сети: 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);
}
}
}
}