首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何区分套接字句柄和文件句柄

如何区分套接字句柄和文件句柄
EN

Stack Overflow用户
提问于 2018-06-22 00:27:11
回答 3查看 989关注 0票数 2

我需要检查windows中进程创建事件中的某些行为,我需要实现一条规则,检查传递给createprocess调用的startupinfo结构,并提取所创建进程的std输入/std输出句柄值。然后,我必须检查这个句柄是否属于tcp套接字。是否有任何api函数可以帮助我获得关于我所拥有的句柄号的任何信息(无论是文件句柄还是套接字句柄)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-06-22 03:56:05

使用GetFileType()函数

检索指定文件的文件类型。 语法 DWORD WINAPI GetFileType( _In_ HANDLE hFile ); 参数 hFile 文件的句柄。 返回值 函数返回下列值之一。 FILE_TYPE_CHAR 指定的文件是字符文件,通常是LPT设备或控制台。 FILE_TYPE_DISK 指定的文件是磁盘文件. FILE_TYPE_PIPE 指定的文件是套接字、命名管道或匿名管道。 FILE_TYPE_REMOTE 没用过。 FILE_TYPE_UNKNOWN 指定文件的类型未知,或者函数失败。

票数 0
EN

Stack Overflow用户

发布于 2019-02-15 12:48:12

使用GetNamedPipeInfo(s,NULL,NULL)区分管道和套接字。

代码语言:javascript
复制
bool is_socket(LPVOID s)
{
  if (GetFileType(s) != FILE_TYPE_PIPE) return false;
  return !GetNamedPipeInfo(s, NULL, NULL, NULL, NULL);
}
票数 3
EN

Stack Overflow用户

发布于 2018-06-22 06:08:24

基于@RemyLebeau的回答,我想我能不能找到一种可靠的方法来区分套接字和管道(这是GetFileType()做不到的),我想出了以下几点,这似乎有效,而且没有明显的缺点。

其要点是,如果传递任何不是套接字的内容,getsockopt()将返回WSAENOTSOCK (= 10038)。因此,这个测试本身就足够了,只要您传递给的任何句柄都是套接字或文件或管道句柄,就足够了。不要简单地传递任何旧句柄(其中有各种各样的句柄),否则它可能会像下面@ HANDLE的第一条评论一样感到困惑。

样本代码:

代码语言:javascript
复制
#include <winsock2.h>                   // * before* windows.h (!)
#include <windows.h>
#include <assert.h>
#include <iostream>

int main ()
{
    WSADATA wsa_data;
    int err = WSAStartup (2, &wsa_data);
    assert (err == 0);

    // Pipe

    HANDLE hReadPipe, hWritePipe;
    BOOL ok = CreatePipe (&hReadPipe, &hWritePipe, NULL, 2048);
    assert (ok);

    int opt;
    int optlen = sizeof (opt);
    err = getsockopt ((SOCKET) hReadPipe, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, &optlen);

    if (err)
    {
        DWORD dwErr = GetLastError ();
        std::cout << "Pipe: " << dwErr << std::endl;
    }
    else
        std::cout << "Pipe: OK" << std::endl;

    CloseHandle (hReadPipe);
    CloseHandle (hWritePipe);

    // Socket

    SOCKET skt = WSASocket (AF_INET, SOCK_STREAM, 0, NULL, 0, 0);
    assert (skt != INVALID_SOCKET);

    optlen = sizeof (opt);
    err = getsockopt (skt, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, &optlen);

    if (err)
    {
        DWORD dwErr = GetLastError ();
        std::cout << "Socket: " << dwErr << std::endl;
    }
    else
        std::cout << "Socket: OK" << std::endl;

    closesocket (skt);
    return 0;
}

输出:

代码语言:javascript
复制
Pipe: 10038
Socket: OK

编辑:--如果您阅读下面的注释,就会看到是否可以引导这些代码相信文件或管道句柄实际上是一个套接字。我们可以知道这一点,因为像ReadFile()WriteFile()这样的函数在文件/管道句柄和套接字上都能很好地工作,如果有可能把其中一个错当成另一个,那就不起作用了。

因此,该代码是(a)安全的,(b)简单的,和(c)有效的所有情况(包括重定向输出,雷米的代码会认为是一个套接字)。因此,我建议这样做。在做其他事情之前,一定要先打电话给WSAStartup()

感谢“HansPassant”和“eryksun”为这篇文章做出了重大贡献。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50979090

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档