windows WSAEFAULT 10014,为什么setsockopt返回-1?

rfbsl7qr  于 2023-01-06  发布在  Windows
关注(0)|答案(1)|浏览(371)

我的setsockopt()调用返回-1,我使用了WSAGetLastError(),它返回WSAEFAULT
错误
10014
地址错误。
系统在尝试使用调用的指针参数时检测到无效的指针地址。如果应用程序传递无效的指针值,或者缓冲区的长度太小,则会发生此错误。例如,如果参数(sockaddr结构)的长度小于sizeof(sockaddr)。
我正在使用MSVC 2022

#include<iostream>
#include<WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

using namespace std;
#define PORT 9909

struct sockaddr_in srv;
fd_set fr, fw, fe;
int nMaxFd;

int main() {

    int nRet = 0;

    // Initialize the WSA variables
    WSADATA ws;
    if (WSAStartup(MAKEWORD(2, 2), &ws) < 0) {
        cout << endl << "WSA failed to initialize";
        WSACleanup();
        exit(EXIT_FAILURE);
    }

    else 
        cout << endl << "WSA initialized";

    // Initialize the socket
    int nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (nSocket < 0) {
        cout << endl << "The socket not opened";
        WSACleanup();
        exit(EXIT_FAILURE);
    }
    else {
        cout << endl << "The socket opened successfully"<<nSocket;
    }

    // Initialize the environment for sockaddr structure
    srv.sin_family = AF_INET;
    srv.sin_port = htons(PORT);
    srv.sin_addr.s_addr = INADDR_ANY;
    memset(srv.sin_zero, 0, 8);

    // setsockpot
    
    int nOptVal = 1;
    int nOptLen = sizeof(nOptVal);
    nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)nOptVal, nOptLen);
    cout << nRet;
    if (!nRet) {
        cout << endl << "The setsockopt call successful";
    }
    else {
        cout << endl << "THe setsockopt call failed";
        cout << endl << WSAGetLastError();
        WSACleanup();
        exit(EXIT_FAILURE);
    }
    
    /* In default, every socket is Blocking socket, we have to use explicitly if wer want non blocking sockets
    // About the Blocking and Non Blocking sockets
    u_long optval = 0;
    nRet = ioctlsocket(nSocket, FIONBIO, &optval);
    if (nRet != 0) {
        cout << endl << "ioctlsocket call failed";
    }
    else {
        cout << endl << "ioctlsocket call passed";
    }
    */

    /*
    // Bind the socket to the local port
    nRet = bind(nSocket, (sockaddr*)&srv, sizeof(sockaddr));
    if (nRet < 0) {
        cout << endl << "Fail to bind to local port";
        exit(EXIT_FAILURE);
    }
    else
        cout << endl << "Successfully bind to local port";

    // Listen the request from client (queues the requests)
    nRet = listen(nSocket, 5);
    if (nRet < 0) {
        cout << endl << "Fail to start listen to local port";
        WSACleanup();
        exit(EXIT_FAILURE);
    }
    else {
        cout << endl << "Started listening to local port";
    }
    nMaxFd = nSocket;
    struct timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    while (1) {
        FD_ZERO(&fr);
        FD_ZERO(&fw);
        FD_ZERO(&fe);

        FD_SET(nSocket, &fr);
        FD_SET(nSocket, &fe);

        cout << endl << "Before select call: " << fr.fd_count;
        // Keep waiting for new requests and proceed as per the request
        nRet = select(nMaxFd + 1, &fr, &fw, &fe, &tv);
        if (nRet > 0) {
            // When someone connects or communicates with a message over a dedicated connection
        }
        else if (nRet == 0) {
            // No connection or any communication request made or you can say that none of the 
            // socket descriptors are ready
            cout << endl << "Nothing on port: " << PORT;
        }
        else {
            // It failed and your application should show some useful message
            cout << endl << "I failed...";
            WSACleanup();
            exit(EXIT_FAILURE);
        }

        cout << endl << "After the select call: " << fr.fd_count;
    }

    */
}

我假设setsockopt()将返回0,但它返回-1:

int nOptVal = 1;
int nOptLen = sizeof(nOptVal);
nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)nOptVal, nOptLen);
wztqucjr

wztqucjr1#

根据setsockopt()文档,WSAEFAULT错误提示您在optval参数中传入了无效指针:
| 错误代码|意义|
| - ------| - ------|
| 错误|* * optval参数指向的缓冲区不在进程地址空间的有效部分**或optlen参数太小。|
当调用setsockopt()时,您需要传入nOptVal变量的 * 内存地址 *,但您传入的是它的 * 值 *,类型转换为指针。1不是变量的有效内存地址,因此出现错误。
试试这个:

int nOptVal = 1;
int nOptLen = sizeof(nOptVal);
nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOptVal, nOptLen);
                                                                  ^
                                                               add this!

相关问题