Как убедиться, что сокет TCP подключается во время создания - PullRequest
2 голосов
/ 22 июля 2011

У меня есть клиентское приложение, которое отправляет пакеты TCP. В настоящее время мое приложение делает это: создает сокет, связывает и отправляет пакеты.

struct sockaddr_in localaddress;
localaddress.sin_port = htons(0);
localaddress.sin_addr.s_addr = INADDR_ANY;

int socket;
socket = socket(AF_INET, SOCK_STREAM, 0));
bind(socket, (struct sockaddr *)&sin,sizeof(struct sockaddr_in) );

А в другом потоке приложение подключается и отправляет пакеты:

struct socketaddr_in remoteaddress;
// omitted: code to set the remote address/ port etc...
nRet = connect (socket, (struct sockaddr * ) & remoteaddress, sizeof (sockaddr_in ));
if (nRet == -1)
    nRet = WSAGetLastError();
if (nRet == WSAEWOULDBLOCK) {
    int errorCode = 0;
    socklen_t codeLen = sizeof(int);
    int retVal = getsockopt(
            socket, SOL_SOCKET, SO_ERROR, ( char * ) &errorCode, &codeLen );
    if (errorCode == 0 && retVal != 0)
        errorCode = errno;
}
/* if the connect succeeds, program calls a callback function to notify the socket is connected, which then calls send() */

Теперь я хочу указать диапазон портов для локального порта, поэтому я изменил код на

nPortNumber = nPortLow;
localaddress.sin_port = htons(nPortNumber);

и выводит nPortNumber в моем диапазоне портов, например (4000 - 5000), до тех пор, пока связывание не будет успешным.

Поскольку я всегда запускаю свой nPortNumber с нижнего порта, если сокет ранее был создан на том же порту, я получаю ошибку WSAEADDRINUSE в виде errorCode, что слишком поздно для меня, поскольку оно уже прошло этап создания сокета. (Почему я не получил WSAEADDRINUSE в bind () или connect ()?)

Есть ли способ получить WSAEADDRINUSE раньше или есть способ создать сокет в диапазоне портов, который связывает и соединяет?

Заранее спасибо!

1 Ответ

0 голосов
/ 22 июля 2011

Я не могу ответить со 100% уверенностью, так как для этого я должен знать, в какой момент вы действительно получаете WSAEADDRINUSE.

В любом случае, это нормально, вы не получаете его на привязку, потому что вы используете INADDR_ANY. IIRC, это фактически задерживает процесс привязки к фактическому соединению (я предполагаю, что тогда он изменяет INADDR на основе маршрутизации для удаленного адреса). Однако, насколько я знаю, вы должны получить ошибку при вызове connect ...

...