Я использую код клиента и сервера в Linux.
Сервер использует TCP / IP с протоколом AF_INET
и SOCK_STREAM
.
Сначала на стороне клиентаЯ (неправильно?) Использовал bind
, чтобы получить правильный addr_info
из связанного списка, который возвращается getaddrinfo
, возвращая соответствующий sockaddr_in.У меня был метод, который выглядел так, как на стороне клиента:
struct sockaddr_in *hostname_to_ip(char *hostname, struct addrinfo *servinfo)
{
int check_sfd;
struct addrinfo hints, *p;
//struct sockaddr_in* ret_value;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int res = getaddrinfo(hostname, NULL, &hints, &servinfo)
if (res != 0) {
fprintf(stderr, "Error: error in getaddrinfo on hostname: %s\n", gai_strerror(res));
exit(EXIT_FAILURE);
}
// getaddrinfo returned a linked list of relevant addresses
// loop through the addresses and return the first one available
for (p = servinfo; p != NULL; p = p->ai_next) {
check_sfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (checksfd < 0)
continue;
if (bind(check_sfd, p->ai_addr, p->ai_addrlen) == 0) { // bind successful
return (struct sockaddr_in*) p->ai_addr;
}
}
return NULL;
}
, позже подключаясь к возвращенному значению в connect.
Форма кода работала хорошо и соединение между клиентом иСервер был успешно установлен (и все функции работали).Однако у меня были утечки памяти из-за неправильного использования freeaddrinfo
.
Поэтому я решил изменить код на следующее:
void hostname_to_ip(char *hostname, int *connection)
{
int check_sfd;
struct addrinfo hints, *p, *servinfo;
//struct sockaddr_in* ret_value;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
int res = getaddrinfo(hostname, NULL, &hints, &servinfo)
if (res != 0) {
fprintf(stderr, "Error: error in getaddrinfo on hostname: %s\n", gai_strerror(s));
exit(EXIT_FAILURE);
}
// getaddrinfo returned a linked list of relevant addresses
// loop through the addresses and return the first one available
for (p = servinfo; p != NULL; p = p->ai_next) {
check_sfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (check_sfd == -1)
continue;
if (connect(check_sfd, p->ai_addr, p->ai_addrlen) == 0) { // connection successful
*connection = check_sfd;
break;
}
close(check_sfd);
}
if (p == NULL) {
// print error
exit(EXIT_FAILURE);
}
freeaddrinfo(&servinfo);
}
Однако теперь я не могуподключиться к серверу, так как connect
всегда возвращает -1 (p
начинается как не NULL
, поэтому подключение к сокету просто не удается).Ошибка: connection refused
.
Когда я изменяю ai_socktype
на SOCK_DGRAM
, соединение установлено успешно, но клиент отправляет ошибку позже при отправке данных (имеет смысл, так как сервер использует SOCK_STREAM
),что довольно странно.
Есть идеи?Код клиента и сервера довольно длинный, поэтому я не прикрепил все это, но попытался добавить всю необходимую информацию.Если чего-то не хватает, прокомментируйте, и я добавлю его.
Это strace
информация о клиенте:
execve("./pcc_client", ["./pcc_client", "localhost", "2001", "1000"], [/* 71 vars */]) = 0
brk(NULL) = 0x2446000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=88205, ...}) = 0
mmap(NULL, 88205, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f0a0f4fa000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\t\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1868984, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a0f4f9000
mmap(NULL, 3971488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0a0ef21000
mprotect(0x7f0a0f0e1000, 2097152, PROT_NONE) = 0
mmap(0x7f0a0f2e1000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c0000) = 0x7f0a0f2e1000
mmap(0x7f0a0f2e7000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0a0f2e7000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a0f4f8000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0a0f4f7000
arch_prctl(ARCH_SET_FS, 0x7f0a0f4f8700) = 0
mprotect(0x7f0a0f2e1000, 16384, PROT_READ) = 0
mprotect(0x601000, 4096, PROT_READ) = 0
mprotect(0x7f0a0f510000, 4096, PROT_READ) = 0
munmap(0x7f0a0f4fa000, 88205) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
getsockname(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 4
connect(4, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(4) = 0
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 4
connect(4, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(4) = 0
brk(NULL) = 0x2446000
brk(0x2467000) = 0x2467000
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=529, ...}) = 0
read(4, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 529
read(4, "", 4096) = 0
close(4) = 0
open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=92, ...}) = 0
read(4, "# The \"order\" line is only used "..., 4096) = 92
read(4, "", 4096) = 0
close(4) = 0
getpid() = 12014
open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=184, ...}) = 0
read(4, "# Dynamic resolv.conf(5) file fo"..., 4096) = 184
read(4, "", 4096) = 0
close(4) = 0
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=88205, ...}) = 0
mmap(NULL, 88205, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f0a0f4fa000
close(4) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 4
read(4, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260!\0\0\0\0\0\0"..., 832) = 832
fstat(4, {st_mode=S_IFREG|0644, st_size=47600, ...}) = 0
mmap(NULL, 2168600, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x7f0a0ed0f000
mprotect(0x7f0a0ed1a000, 2093056, PROT_NONE) = 0
mmap(0x7f0a0ef19000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0xa000) = 0x7f0a0ef19000
mmap(0x7f0a0ef1b000, 22296, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f0a0ef1b000
close(4) = 0
mprotect(0x7f0a0ef19000, 4096, PROT_READ) = 0
munmap(0x7f0a0f4fa000, 88205) = 0
open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0644, st_size=233, ...}) = 0
read(4, "127.0.0.1\tlocalhost\n127.0.1.1\tmi"..., 4096) = 233
read(4, "", 4096) = 0
close(4) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
write(1, "x\n", 2x
) = 2
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
write(1, "4\n", 24
) = 2
write(1, "\n", 1
) = 1
connect(4, {sa_family=AF_INET, sin_port=htons(53511), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)
close(4) = 0
write(1, "Error: couldn't connect to hostn"..., 56Error: couldn't connect to hostname. Connection refused
) = 56
exit_group(1) = ?
+++ exited with 1 +++
Спасибо!