如何确保 TCP 套接字在创建时连接

Posted

技术标签:

【中文标题】如何确保 TCP 套接字在创建时连接【英文标题】:How to make sure a TCP socket connects at creation time 【发布时间】:2011-07-22 03:25:15 【问题描述】:

我有一个发送 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,这对我来说太晚了,因为它已经通过了套接字创建阶段。 (为什么我在 bind() 或 connect() 没有得到 WSAEADDRINUSE?)

有没有一种方法可以让我更早地获得 WSAEADDRINUSE,或者有没有一种方法可以在绑定和连接的端口范围内创建一个套接字?

提前致谢!

【问题讨论】:

你的应用需要你控制源端口吗?另外,您是否真的设置了要连接的远程地址,而为了简洁起见,您只是从代码中省略了它? @evil-otto ,我的应用程序需要控制源端口在端口范围内。是的,我正在设置远程地址。 【参考方案1】:

我不能 100% 肯定地回答,我应该知道你在什么时候真正得到WSAEADDRINUSE

在任何情况下,您在绑定时没有得到它是正常的,因为您使用INADDR_ANY。 IIRC,这实际上将绑定过程延迟到实际连接(我的猜测是它会根据远程地址的路由更改 INADDR)。但是,据我所知,您实际上应该在调用连接时收到错误...

【讨论】:

是的,我也这么认为。但是 connect() 只返回 WSAEWOULDBLOCK。

以上是关于如何确保 TCP 套接字在创建时连接的主要内容,如果未能解决你的问题,请参考以下文章

c TCP中的套接字我如何测试连接?

如何在 C++/QT 中使用 TCP 服务器套接字创建 Http 服务器

如何在 python asyncio 中处理 tcp 客户端套接字自动重新连接?

Python 31 TCP协议 socket套接字

如何在 VB.NET 中检查 TCP 服务器(套接字)与 TCP 客户端的连接状态

在 Erlang 中通过 RPC 在远程节点上创建套接字时,无法接受套接字上的连接