Windows c socket:select()给出了WSAENOTSOCK错误

时间:2016-06-03 10:43:20

标签: c windows sockets visual-studio-2015 winsock

我正在使用winsock连接到远程服务器。我在连接套接字方面取得了成功,但是当我尝试使用select获取套接字详细信息时,它表示套接字不存在( WSAENOTSOCK )。

N.B:我正在以Visual Studio win控制台应用程序执行此代码,我的操作系统是Windows 8。

我的代码 (假设代码执行从run_client函数开始,测试结构具有所有选项)。此外,函数在不同的文件中,所以我需要多次调用WSAStartup

#define _CRT_SECURE_DEPRECATE_MEMORY
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <signal.h>
#include <sys/types.h>
#include <Winsock2.h>
#include <memory.h>
#include <WS2tcpip.h>

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

int run_client(struct test * test)
{
    int startup;
    int result = 0;
    fd_set read_set, write_set, excep_fd;
    struct timeval now;
    struct timeval* timeout = NULL;
    struct iperf_stream *sp;

    FD_ZERO(&excep_fd);

    if (soc_connect(test) < 0)
        return -1;

    printf("Run client : success in making socket\n");

    memcpy(&read_set, &test->read_set, sizeof(fd_set));
    memcpy(&write_set, &test->write_set, sizeof(fd_set));

    int iResult;
    WSADATA wsaData;

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return -1;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        printf("Could not find a usable version of Winsock.dll\n");
        WSACleanup();
        return -1;
    }
    else
    {
        printf("The Winsock 2.2 dll was found okay\n");
    }


    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    result = select(test->ctrl_sck + 1, &read_set, 0, 0, &tv);

    if (SOCKET_ERROR == result)
    {
        switch (WSAGetLastError())
        {
            case WSANOTINITIALISED:
                printf("select_result error  : WSANOTINITIALISED\n");
                break;
            case WSAEFAULT:
                printf("select_result error  : WSAEFAULT\n");
                break;
            case WSAENETDOWN:
                printf("select_result error  : WSAENETDOWN\n");
                break;
            case WSAEINTR:
                printf("select_result error  : WSAEINTR\n");
                break;
            case WSAEINPROGRESS:
                printf("select_result error  : WSAEINPROGRESS\n");
                break;
            case WSAENOTSOCK:
                printf("select_result error  : WSAENOTSOCK\n");
                break;
            default:
                printf("select_result errors  : %d\n", WSAGetLastError());
                break;
        }
        i_errno = WSAGetLastError();
        closesocket(test->ctrl_sck);
        WSACleanup();
        return -1;
    }
    else if (result == 0)
    {
        printf("select_result : timeout : %d\n", result);
        WSACleanup();
        return -1;
    }
    else
    {
        WSACleanup();
    }
}

int soc_connect(struct test *test)
{
    FD_ZERO(&test->read_set);
    FD_ZERO(&test->write_set);

    printf("Making cookie\n");

    make_cookie(test->cookie);

    printf("Success in Making cookie\n");

    /* Create and connect the control channel */
    if (test->ctrl_sck < 0)
    {
       test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, 0, test->server_hostname, test->server_port);
    }

    if (test->ctrl_sck < 0) {
        i_errno = IECONNECT;
        return -1;
    }

    FD_SET(test->ctrl_sck, &test->read_set);
    return 0;
}

void make_cookie(char *cookie)
{
    static int randomized = 0;
    char hostname[500];
    struct timeval tv;
    char temp[1000];

    if ( ! randomized )
        srand((int) time(0) ^ getpid());

    (void) gethostname(hostname, sizeof(hostname));
    (void) gettimeofday(&tv, 0);
    (void) snprintf(temp, sizeof(temp), "%s.%ld.%06ld.%08lx%08lx.%s", hostname, (unsigned long int) tv.tv_sec, (unsigned long int) tv.tv_usec, (unsigned long int) rand(), (unsigned long int) rand(), "1234567890123456789012345678901234567890");

    memcpy(cookie, temp, 36);
    cookie[36] = '\0';
}

int netdial(int domain, int proto, char *local, int local_port, char *server, int port)
{
    struct addrinfo hints, *local_res = NULL, *server_res = NULL;
    int s;

    WSADATA wsaData;
    int iResult;
    INT iRetval;

    char port_str[6];
    snprintf(port_str, 6, "%d", port);

    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed: %d\n", iResult);
        return -1;
    }

    if (local) {
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = domain;
        hints.ai_socktype = proto;
        if (getaddrinfo(local, port_str, &hints, &local_res) != 0)
        {
            WSACleanup();
            printf("Net dial : 0\n");
            return -1;
        }
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = domain;
    hints.ai_socktype = proto;
    hints.ai_protocol = IPPROTO_TCP;
    if (getaddrinfo(server, port_str, &hints, &server_res) != 0)
    {
        WSACleanup();
        return -1;
    }


    s = socket(server_res->ai_family, server_res->ai_socktype, server_res->ai_protocol);
    if (s == INVALID_SOCKET) {
        if (local)
        {
            if (local_res != NULL)
                freeaddrinfo(local_res);
        }
        freeaddrinfo(server_res);
        WSACleanup();
        return -1;
    }

    printf("Socket created\n");

    if (local) {
        if (local_port) {
            printf("Net dial : 3\n");
            struct sockaddr_in *lcladdr;
            lcladdr = (struct sockaddr_in *)local_res->ai_addr;
            lcladdr->sin_port = htons(local_port);
            local_res->ai_addr = (struct sockaddr *)lcladdr;
        }

        if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
            _close(s);
            WSACleanup();
            freeaddrinfo(local_res);
            freeaddrinfo(server_res);
            printf("Net dial : 4\n");
                return -1;
        }
        freeaddrinfo(local_res);
    }

    iResult = connect(s, server_res->ai_addr, (int)server_res->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        closesocket(s);
        s = INVALID_SOCKET;
    }

    freeaddrinfo(server_res);

    if (s == INVALID_SOCKET) {
        WSACleanup();
        return -1;
    }

    printf("Socket connected\n");

    WSACleanup();
    return s;
}

输出

Making cookie
Success in Making cookie
Socket created
Socket connected
Run client : success in making socket
The Winsock 2.2 dll was found okay
select_result errors  : WSAENOTSOCK

我已经搜索了这个问题并尝试了很多解决方案,但我找不到我的解决方案。请一个人请帮帮忙。

1 个答案:

答案 0 :(得分:3)

  

函数在不同的文件中,所以我需要多次调用WSAStartup

不,你没有。这是你的捏造。您需要在流程开始时调用WSAStartup()一次,并在流程结束时调用WSACleanup()一次。

我无法想象你是如何或在何处得到这个想法的,但这是错误的。 Winsock既不知道也不关心你有多少.c文件。