sziasztok
az alábbi jelenséget már sok helyen tapasztaltam, de néha az én "szerveremen" is előfordul, ezért szeretnék utánajárni.
a jelenség: fájlátvitel (legtöbbször feltölteni szoktam, de előfordul letöltésnél is) egy vagy több nagyobb fájlra (de lassú kapcsolaton kisebb fájl is lehet), a lényeg, hogy sokáig tartson az átvitel. miután a feájl feltöltődik (vag le), elér 100%-ig, utána megáll. az ftp kliens szerintem nem kap valami visszajelzést, mondjuk az utolsó bájt vételekor egy "rendben" választ vagy ilyesmi. ekkor a ftp kliens is "megfagy", kilépni is alig lehet. (főleg total commandert használok, de láttam már ilyet gftp-vel és filezillával is)
miközben a kapcsolat látszólag megfagy, másik klienssel be lehet jelentkezni minden további nélkül (tehát nem a ftp szerver fagy le), és látszik, hogy valóban a fájl teljesen feltöltődik, bájtra pontosan.
m,ikor a kliens "lefagy", az abortot buzgón nyomkodva ki lehet lépni, ilyenkor próbál még parancsokat küldeni, de azok sem mennek, olyan, mintha a teljes felépített kapcsolat megbénulna. újrakapcsolódva minden remekül működik tovább.
fogalmam sincs, mitől lehet ez, természetesen a lkogokban semmiféle nyoma nincs.
esetleg a command csatorna hosszú tétlenség miatt bezárja a megnyitott kapcsolatot? vagy esetleg a tűzfalon lezár a csatorna?
van aki tudja a megoldást? előre is köszönöm.
- 1588 megtekintés
Hozzászólások
szerintem a tűzfal lebontja a nat táblát, ezért akad meg a parancscsatorna.
- A hozzászóláshoz be kell jelentkezni
Nagyon valószínű, hogy erről van szó.
Javaslat: nyergeljük meg a
socket()
függvényt, és ha TCP socket-et hoznak létre, akkor mindjárt állítsunk is be rá TCP keepalive-ot (a felhasználó az első szonda előtti csend idejét ill. a szondák közötti intervallumot egyaránt a
KA_IDLE_SECS
környezeti változóval szabályozhatja).
/*
$Id: keepalive.c,v 1.3 2009-08-27 23:53:00 lacos Exp $
Compilation:
gcc -ansi -pedantic -Wall -Wextra -Wformat=2 \
-fPIC -shared -o keepalive.so keepalive.c
Usage:
LD_PRELOAD=./keepalive.so KA_IDLE_SECS=60 ftp
*/
#define _GNU_SOURCE 1
#include <sys/socket.h> /* AF_INET */
#include <netinet/in.h> /* IPPROTO_TCP */
#include <netinet/tcp.h> /* TCP_KEEPIDLE -- Linux-specific */
#include <unistd.h> /* close() */
#include <errno.h> /* errno */
#include <stdlib.h> /* getenv() */
#include <limits.h> /* INT_MAX */
#include <dlfcn.h> /* dlsym() */
static int (*real_socket)(int, int, int),
idlearg;
int
socket(int domain, int type, int protocol)
{
int sock;
sock = (*real_socket)(domain, type, protocol);
if (-1 != sock && AF_INET == domain && SOCK_STREAM == type
&& (0 == protocol || IPPROTO_TCP == protocol)) {
int optval;
optval = 1;
if (0 == setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof optval)
&& 0 == setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idlearg,
sizeof idlearg)
&& 0 == setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &idlearg,
sizeof idlearg)) {
return sock;
}
(void)close(sock);
sock = -1;
errno = EPROTONOSUPPORT;
}
return sock;
}
static void __attribute__((constructor)) /* gcc-specific */
setup(void)
{
const char *envstr;
envstr = getenv("KA_IDLE_SECS");
if (0 != envstr) {
long envval;
char *endptr;
errno = 0;
envval = strtol(envstr, &endptr, 0);
if ('\0' != envstr[0] && '\0' == *endptr && 0 == errno && 0L < envval
&& envval <= (long)INT_MAX) {
void *sym;
sym = dlsym(RTLD_NEXT, "socket");
if (0 != sym) {
idlearg = envval;
*(void **)&real_socket = sym;
return;
}
}
}
abort();
}
Megjegyzések: ha nem Linuxon vagyunk, akkor jó eséllyel a TCP_* socket option-ök helyett a megfelelő (globális) kernelparamétereket kell reszelnünk. Ha nem gcc-t használunk, akkor a shared lib inicializálását máshogyan kell megoldani (esetleg a
setup()
tartalmának
socket()-be ágyazásával
és legelső híváskori futtatásával.)
- A hozzászóláshoz be kell jelentkezni
Ugyan ezt tapasztalom, midnight commanderrel, jellemzően 4-12 GB-s fájlok letöltésekor.
- A hozzászóláshoz be kell jelentkezni
Egyéb megoldás nincs? Nem nagyon szeretnék kernelt buherálni emiatt...
- A hozzászóláshoz be kell jelentkezni