POSIX сокет-клиент, подключающийся к себе

Я получаю очень странное поведение со своим кодом сокета клиента TCP, поэтому я написал простую тестовую программу.

Код ниже предназначен для постоянной повторной попытки подключения к серверу (127.0.0.1:36000) пока не соединится. Компилируется с g++ 4.8.5 с -std=c++98 (C ++ 03/11 не может быть использован).

#include <arpa/inet.h>
#include <cctype>
#include <cerrno>
#include <cstring>
#include <iostream>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

int main()
{
int sd = -1;

while (true)
{
close(sd);

std::cout << "trying to connect" << std::endl;

if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
std::cerr << strerror(errno) << std::endl;
continue;
}

std::cout << "socket created " << sd << std::endl;

struct sockaddr_in addr;
memset((char *)&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;

if (!inet_aton("127.0.0.1", &addr.sin_addr))
{
std::cerr << strerror(errno) << std::endl;
continue;
}
std::cout << "translated ip" << std::endl;

addr.sin_port = htons(36000);

if (connect(sd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0)
{
std::cerr << "Error connecting socket" << std::endl;
continue;
}

std::cout << "connected " << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port) << std::endl;
std::cout << "write " << write(sd, "from client", 11) << std::endl;

char buf[1024] = {0};
int size;
while ((size = read(sd, buf, 1024, 0, NULL, NULL)) > -1)
{
buf[size] = 0;
std::cout << "received " << size << " ["  << buf << "]" << std::endl;
}

std::cout << "stopped" << std::endl;
}

return 0;
}

Несмотря на то, что нет сервера или какой-либо другой программы, использующей порт 36000, connect вызов успешно, как и write, Я получаю вывод, который выглядит так:

trying to connect
socket created 3
translated ip
Error connecting socket
trying to connect
socket created 3
translated ip
Error connecting socket
...
...
...
trying to connect
socket created 3
translated ip
connected 127.0.0.1:36000
write 11
received 11 [from client]

Если порт изменен на любой другой неиспользуемый порт (35999, 36001 и т. Д.), connect будет только сбой (соединение отказано). Другие порты никогда не соединяются.

Аргументы recvfrom не изменяются, если они присутствуют.

Кроме того, это происходит только тогда, когда время ожидания сокета не истекло. Если время сокета истекло, connect не удастся.

Бег netstat -an в то время как read заблокирован вернется

tcp        0      0 127.0.0.1:36000         127.0.0.1:36000         ESTABLISHED

Это происходит на CentOS 6,7 и 7 VMS.

Что происходит? Что-то странное в порте 36000? Это Centos /connect ошибка? Я делаю что-то глупое?

Это частичная копия Как вы можете установить TCP-соединение с тем же портом? но это все еще не объясняет, почему это происходит только на порту 36000.

0

Решение

Когда я выполняю вашу программу с запущенным tcpdump, я получаю некоторые интересные результаты.

sudo tcpdump -i lo

...
14:51:16.477170 IP localhost.35988 > localhost.36000: Flags [S], seq 3826079620, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477173 IP localhost.36000 > localhost.35988: Flags [R.], seq 0, ack 3826079621, win 0, length 0
14:51:16.477203 IP localhost.35990 > localhost.36000: Flags [S], seq 2431563950, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477206 IP localhost.36000 > localhost.35990: Flags [R.], seq 0, ack 2431563951, win 0, length 0
14:51:16.477247 IP localhost.35992 > localhost.36000: Flags [S], seq 3688613148, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477250 IP localhost.36000 > localhost.35992: Flags [R.], seq 0, ack 3688613149, win 0, length 0
14:51:16.477282 IP localhost.35994 > localhost.36000: Flags [S], seq 1503921089, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477285 IP localhost.36000 > localhost.35994: Flags [R.], seq 0, ack 1503921090, win 0, length 0
14:51:16.477315 IP localhost.35996 > localhost.36000: Flags [S], seq 2868111150, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477318 IP localhost.36000 > localhost.35996: Flags [R.], seq 0, ack 2868111151, win 0, length 0
14:51:16.477348 IP localhost.35998 > localhost.36000: Flags [S], seq 281293569, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477351 IP localhost.36000 > localhost.35998: Flags [R.], seq 0, ack 281293570, win 0, length 0
14:51:16.477381 IP localhost.36000 > localhost.36000: Flags [S], seq 3196081163, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 0,nop,wscale 7], length 0
14:51:16.477386 IP localhost.36000 > localhost.36000: Flags [S.], seq 3196081163, ack 3196081164, win 65495, options [mss 65495,sackOK,TS val 95720198 ecr 95720198,nop,wscale 7], length 0
14:51:16.477422 IP localhost.36000 > localhost.36000: Flags [.], ack 1, win 512, options [nop,nop,TS val 95720198 ecr 95720198], length 0

Эти выходные данные показывают, что сокет фактически выполняет TCP-трехстороннее рукопожатие с собой. По какой-то причине (по крайней мере, в CentOS 6.7) порт источника увеличивается на 2, что предотвращает проблему с портами 35999, 36001.

В RFC 793 это говорит об этом типе соединения как одновременное соединение.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]