我可以从使用 c++ 和 windows 连接到服务器的套接字获得啥信息?

Posted

技术标签:

【中文标题】我可以从使用 c++ 和 windows 连接到服务器的套接字获得啥信息?【英文标题】:What information can I get from a socket connected to a server using c++ and windows?我可以从使用 c++ 和 windows 连接到服务器的套接字获得什么信息? 【发布时间】:2021-08-15 17:48:44 【问题描述】:

我有一个服务器,当客户端连接到服务器时,我想从客户端获取所有信息并用它创建一个结构。 我可以获得什么信息? 我知道我可以从客户端获取 ipv4 和端口,还有什么可以获取的吗?

这是一个简短的方法:

#undef UNICODE

#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>

#pragma comment (lib, "Ws2_32.lib")

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 32406

int main()

    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    sockaddr_in hint;
    hint.sin_addr.S_un.S_addr = INADDR_ANY;
    hint.sin_port = htons(DEFAULT_PORT);
    hint.sin_family = AF_INET;

    SOCKET listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
    bind(listeningSocket, (sockaddr*)&hint, sizeof(sockaddr_in));
    listen(listeningSocket, SOMAXCONN);

    sockaddr_in socketInfo;
    int socketInfoLen = sizeof(socketInfo);
    SOCKET clientSocket = accept(listeningSocket, (sockaddr*)&socketInfo, &socketInfoLen);

    std::cout << inet_ntoa(socketInfo.sin_addr) << std::endl;
    std::cout << socketInfo.sin_port << std::endl;

    shutdown(clientSocket, SD_BOTH);
    closesocket(clientSocket);
    closesocket(listeningSocket);
    WSACleanup();

    return 0;

【问题讨论】:

套接字和网络不是 C++ (ISO 14882) 的一部分。它们是由其他东西提供的设施,例如 Boost ASIO 或操作系统。您需要参考您在平台上使用的设施的文档。 您使用的是什么 API? 我现在不在家,对不起,我回家后会发布一些代码。 我正在使用 windows sockets api 【参考方案1】:

getsockopt 提供了大量信息。它是另一个答案声称的超集,例如

SO_BSP_STATE 返回套接字使用的本地地址、本地端口、远程地址、远程端口、套接字类型和协议。

由于你有一个 TCP 套接字,你会特别感兴趣

IPPROTO_TCP socket options

通过WSAIoctl可以得到不同的信息,例如

TCP_INFO_v1 structure

其中一些细节将是本地套接字选项(例如阻塞或非阻塞),其他细节将与连接本身有关(例如协商的窗口大小)。一些关于远程客户端的信息会被泄露,尽管不像您使用定制的指纹识别工具那样多。

【讨论】:

你能告诉我如何使用带有 SO_BSP_STATE 标志的 getsockopt 吗?我在互联网上找不到任何有用的东西,或者不知道要寻找什么。谢谢! @ClaudiuHBann:The official documentation 看起来很有用。如果在阅读之后您仍然无法使其工作,那么可能值得提出一个新的专业问题。但是这些特定信息更容易获得via getsockname() and getpeername() as Remy commented already 好像我不知道怎么读 :)) 谢谢【参考方案2】:

客户端没有明确发送的唯一信息是sockaddr_in 结构,即端口和源IP 地址。当然,您只有在客户端启动传输(使用 UDP 发送数据包或使用 TCP 连接)时才会收到此信息。

要获取其他任何内容,客户端需要将其作为常规通信的一部分发送。

【讨论】:

"你得到的唯一信息......是......端口和源 IP 地址" - 这并不完全正确。在 TCP 中,您还可以获取客户端连接的目标 IP 地址和端口。由于服务器绑定到INADDR_ANY,客户端可以connect() 到任何属于服务器的IP。 accept()getpeername() 会告诉你客户端来自哪里,而getsockname() 会告诉你客户端实际连接到哪里。在 UDP 中,还有WSARecvMsg(),它可以告诉你一个数据包被发送到哪个 IP 以及实际接收到的网络接口。 如果是 TCP 套接字(这是),也应该有可能(尽管可能很棘手)获取有关 TCP 标头中协商的 TCP 选项的信息,例如窗口大小等。 我认为很明显他想要关于客户端的信息,而不是服务器

以上是关于我可以从使用 c++ 和 windows 连接到服务器的套接字获得啥信息?的主要内容,如果未能解决你的问题,请参考以下文章

连接到 IRC 服务器 C++ Windows 10 Visual Studio

我可以从 Java EE webapp 使用 Windows 身份验证连接到 SQL Server 吗?

是否可以从 C# 应用程序连接到 32 位 C++ RPC 服务器应用程序

是否有 C++ CalDav 协议库可以连接到 iCloud//Yahoo [关闭]

多线程在 C++ 中的 Windows 中将多个客户端连接到单个服务器

C++ 客户端通过 SSL 连接到 IBM MQ