Я хочу отлаживать взаимодействия TCP / IP для программы, которую я улучшаю.У меня нет root-доступа (поэтому нет tcpdump и т. Д.), Но приложение работает под моим собственным идентификатором.Я мог бы использовать, например, strace для перехвата системных вызовов, но есть ли альтернативы, которые стоит рекомендовать по этому поводу?Если так, почему - что они предлагают?Предпочтительная командная строка (на моем ПК сейчас не установлен X-сервер :-(), но также интересны графические интерфейсы.
В идеале это будет выглядеть примерно так:
app listening on port <portA>
app listening on port <portB>
client connection #1 accepted on listening port <portA> to local port <portC>
from remote <hostX:portXA>
app sent #1 <number> bytes "<data dump...>"
app received from client #1 <number> bytes "<data dump...>"
client #1 closed connection
Поцарапает одинвместе, но слишком много колес, чтобы изобретать их как есть ....
Заранее спасибо.
ОБНОВЛЕНИЕ: и paulrubel, и ypnos сделали очень полезные предложения ... (хотелось бы, чтобы я принялоба ответа, поскольку они различны и одинаково хороши.) Код, реализующий предложенный Полом перехват LD_PRELOAD, следует:
// TCP comms trace library
// as per http://www.jayconrod.com/cgi/view_post.py?23
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef ssize_t (*Recv)(int s, void* buf, size_t len, int flags);
ssize_t recv(int s, void* buf, size_t len, int flags)
{
static Recv real = NULL;
if (!real)
real = (Recv)dlsym(RTLD_NEXT, "recv");
fprintf(stderr, "> recv(s '%d', buf %p, len %lld, flags %d)...\n",
s, buf, len, flags);
ssize_t result = real(s, buf, len, flags);
fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
s, buf, len, flags, result);
return result;
}
typedef ssize_t (*Send)(int s, const void* buf, size_t len, int flags);
ssize_t send(int s, const void* buf, size_t len, int flags)
{
static Send real = NULL;
if (!real)
real = (Send)dlsym(RTLD_NEXT, "send");
fprintf(stderr, "> send(s '%d', buf %p, len %lld, flags %d)...\n",
s, buf, len, flags);
ssize_t result = real(s, buf, len, flags);
fprintf(stderr, "< recv(s '%d', buf %p, len %lld, flags %d) return %lld\n",
s, buf, len, flags, result);
return result;
}
typedef int (*Connect)(int s, const struct sockaddr* serv_addr, socklen_t addrlen);
int connect(int s, const struct sockaddr* serv_addr, socklen_t addrlen)
{
static Connect real = NULL;
if (!real)
real = (Connect)dlsym(RTLD_NEXT, "connect");
fprintf(stderr, "> connect(s %d, sockaddr %p, addrlen %d)\n",
s, (void*)serv_addr, addrlen);
int result = real(s, serv_addr, addrlen);
fprintf(stderr, "< connect(s %d, sockaddr %p, addrlen %d) return %d\n",
s, (void*)serv_addr, addrlen, result);
return result;
}
typedef int (*Accept)(int s, const struct sockaddr* serv_addr, socklen_t* addrlen);
int accept(int s, struct sockaddr* serv_addr, socklen_t* addrlen)
{
static Accept real = NULL;
if (!real)
real = (Accept)dlsym(RTLD_NEXT, "accept");
fprintf(stderr, "> accept(s %d, sockaddr %p, addrlen %p)\n",
s, (void*)serv_addr, addrlen);
int result = real(s, serv_addr, addrlen);
fprintf(stderr, "< accept(s %d, sockaddr %p, addrlen %p -> %d) return %d\n",
s, (void*)serv_addr, addrlen, *addrlen, result);
return result;
}