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

发布于 2024-11-25 13:15:34 字数 1430 浏览 6 评论 0原文

我有一个发送 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,或者有没有办法在绑定和连接的端口范围中创建套接字?

提前致谢!

I have a client application that sends TCP packets. Currently, my application does this:
creates a socket, binds and sends the packets.

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) );

And in another thread, the application connects and sends the packets:

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() */

Now I want to specify a port range for local port, so I changed the code to

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

and loops nPortNumber in my port range, e.g ( 4000 - 5000 ) until the bind succeeds.

Since I always start my nPortNumber from the low port, if a socket is previously created on the same port, I get the WSAEADDRINUSE error as errorCode, which is too late for me because it has already passed the socket creation stage. (Why didn't I get WSAEADDRINUSE at bind() or connect()?)

Is there a way I can get the WSAEADDRINUSE earlier or is there a way to create a socket in the port range that binds and connects?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

澉约 2024-12-02 13:15:34

我无法 100% 肯定地回答,因为我应该知道您在什么时候真正获得了 WSAEADDRINUSE

无论如何,在绑定时得不到它是正常的,因为您使用了 INADDR_ANY。 IIRC,这实际上延迟了实际连接的绑定过程(我的猜测是它随后根据远程地址的路由更改了 INADDR)。但是,据我所知,您应该在调用 connect 时实际收到错误...

I cannot answer with 100% certainty as for that I should know at which point you actually get WSAEADDRINUSE.

IN any case, it is normal you don't get it at bind, because you use INADDR_ANY. IIRC, this actually delays the bind process to the actual connect (my guess is it then changes the INADDR based on routing for the remote addr). However, as far as I know, you should then actually get the error at the call of connect...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文