C
C
CodeInside2017-05-03 15:02:59
C++ / C#
CodeInside, 2017-05-03 15:02:59

Why can't create a socket?

With this version (below) of creating a socket after bind, error 10047 (Address is incompatible with the selected protocol) crashes:

DWORD WINAPI ThreadForAccept(LPVOID lpParam)
{
    SOCKET sock = socket(AF_INET,
        SOCK_STREAM,
        IPPROTO_TCP);
 
    if (sock == SOCKET_ERROR) {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    int iOptval = 1;
    int res = setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
        (char *)&iOptval, sizeof(iOptval));
 
    if (res == SOCKET_ERROR) {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    SOCKADDR_IN saLocal;
 
    int iFamily = AF_UNSPEC;
 
    saLocal.sin_family = (ADDRESS_FAMILY)iFamily;
    saLocal.sin_port = htons((u_short)IP_PORT);
    saLocal.sin_addr.s_addr = htonl(INADDR_ANY);
 
    res = bind(sock,
        (sockaddr*)&saLocal,
        sizeof(saLocal));
 
    if (res == SOCKET_ERROR) {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    res = listen(sock, CONNECTION_QUEUE_SIZE);
 
    if (res == SOCKET_ERROR)    {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    while (true) {
        int iAddrSize = sizeof(sockaddr_in);
        ClientInfo clientinfo;
        clientinfo.socket = accept(
            sock,
            (sockaddr*)&(clientinfo.addr),
            &iAddrSize);
 
        if (clientinfo.socket == INVALID_SOCKET) {
            ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
            break;
        }
 
        TCHAR str[30];
        wsprintf(str, L"The client joined");
 
        SetWindowText(ProcessManagerServerDlg::ptr->hDialog, str);
        HANDLE hThread = CreateThread(0, 0, ThreadForReceive, (LPVOID)&clientinfo, 0, 0);
        CloseHandle(hThread);
    }
    closesocket(sock);
    WSACleanup();
    EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), true);
    return 0;
}

But with this (code below), error 10013 (An attempt was made to access the socket by a method prohibited by access rights (even if I run the .exe with administrator rights).
DWORD WINAPI ThreadForAccept(LPVOID lpParam)
{
    SOCKET sock = socket(AF_INET,
        SOCK_STREAM,
        IPPROTO_TCP);
 
    if (sock == SOCKET_ERROR) {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    sockaddr_in local;
    local.sin_addr.S_un.S_addr = INADDR_ANY;
    local.sin_family = AF_INET;
    local.sin_port = htons(IP_PORT);
 
    res = bind(sock,
        (sockaddr*)&local,
        sizeof(local));
 
    if (res == SOCKET_ERROR) {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    res = listen(sock, CONNECTION_QUEUE_SIZE);
 
    if (res == SOCKET_ERROR)    {
        ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
        closesocket(sock);
        WSACleanup();
        EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), TRUE);
        return 0;
    }
 
    while (true) {
        int iAddrSize = sizeof(sockaddr_in);
        ClientInfo clientinfo;
        clientinfo.socket = accept(
            sock,
            (sockaddr*)&(clientinfo.addr),
            &iAddrSize);
 
        if (clientinfo.socket == INVALID_SOCKET) {
            ProcessManagerServerDlg::ptr->MessageAboutError(WSAGetLastError());
            break;
        }
 
        TCHAR str[30];
        wsprintf(str, L"The client joined");
 
        SetWindowText(ProcessManagerServerDlg::ptr->hDialog, str);
        HANDLE hThread = CreateThread(0, 0, ThreadForReceive, (LPVOID)&clientinfo, 0, 0);
        CloseHandle(hThread);
    }
    closesocket(sock);
    WSACleanup();
    EnableWindow(GetDlgItem(ProcessManagerServerDlg::ptr->hDialog, IDC_LAUNCH), true);
    return 0;
}

Can you please help solve this problem?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry, 2017-05-03
@TrueBers

int iFamily = AF_UNSPEC;
 
saLocal.sin_family = (ADDRESS_FAMILY)iFamily;

How are you going to create a socket with an undefined type? It should be in your case either AF_INET or AF_INET6.
And about WSAEACCESS you read MSDN ? There is even a sign there, with explanations of errors and in what cases they appear, and below it is indicated:
Note A socket that is using the SO_EXCLUSIVEADDRUSE option must be shut down properly prior to closing it. Failure to do so can cause a denial of service attack if the associated service needs to restart.

I also advise you to read about TCP in general. About its state machine, what states it has, what is a semi-closed socket, what is graceful shutdown, etc.
When you use SO_EXCLUSIVEADDRUSE, you should not have dangling connections in any of the states. That is, not only ESTABLISHED, but also various FIN-WAIT, TIME-WAIT, CLOSE-WAIT should not be either. If you always bind to the same port, then using SO_EXCLUSIVEADDRUSE on clients will be very problematic, because you will always run into a semi-closed port.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question