1. 程式人生 > >【網絡編程】使用getnameinfo()/getaddrinfo()/InetPton()

【網絡編程】使用getnameinfo()/getaddrinfo()/InetPton()

har addrinfo turn num instead specified com accep host

1、簡要

從前用的網絡編程函數現在又做了一定的改動,報了這麽3個錯誤。

error C4996: ‘inet_ntoa‘: Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

error C4996: ‘gethostbyaddr‘: Use getnameinfo() or GetNameInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

error C4996: ‘inet_ntoa‘: Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings

2、解決方法1

右鍵屬性-屬性頁選擇【C/C++】->【常規】->【SDL檢查】 選擇為否。

技術分享圖片

3、代碼解決

既然已經明確提示需要換更安全的函數,那就按照要求來就好了。

serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//自己的IP或者127.0.0.1

改為:

//新改進代碼
InetPton(AF_INET, _T("127.0.0.1"), &serverAddr.sin_addr.s_addr);

gethostbyaddr()改用getnameinfo();

inet_ntop()改用getaddrinfo();

修改後的代碼:

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

/*
1. 初始化環境        wsastartup
2. 創建套接字        socket
3. 綁定套接字        bind
4. 監聽套接字        listen
5. 處理套接字連接      accept
6. 發送接收數據       send/recv
7. 關閉套接字        closesocket
8. 清理環境         wsacleanup
*/
int main()
{
    // 1. 初始化環境     wsastartup
    WSADATA wsd = { 0 };
    int re = WSAStartup(MAKEWORD(2, 2), &wsd);
    if (re != 0) { return 0; }
    if (LOBYTE(wsd.wVersion) != 2 ||
        HIBYTE(wsd.wVersion) != 2)
    {
        return 0;
    }
    // 2. 創建套接字     socket
    SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (listenSock == INVALID_SOCKET)
    {
        return 0;
    }
    // 3. 綁定套接字     bind
    sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(0x5566);
        //舊代碼
    //serverAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//自己的IP或者127.0.0.1

    //新改進代碼
    InetPton(AF_INET, _T("127.0.0.1"), &serverAddr.sin_addr.s_addr);

    re = bind(listenSock, (sockaddr *)&serverAddr, sizeof(serverAddr));

    // 4. 監聽套接字     listen
    re = listen(listenSock, SOMAXCONN);

    // 5. 處理套接字連接   accept
    sockaddr_in clientAddr;
    int size = sizeof(clientAddr);
    SOCKET sToClientSock = accept(
        listenSock, (sockaddr *)&clientAddr, &size);

    //測試獲取的結果
    //更換為新函數查看使用結果
    //舊 主機名
    hostent * pHost = gethostbyaddr((char *)&serverAddr.sin_addr, 4, AF_INET);
    //舊  IP地址
    char * p = inet_ntoa(*(struct in_addr *) (*pHost->h_addr_list));
    

    //新代碼測試
    ///////////////////////////////////////////////////////////////////
    struct addrinfo *ptr = NULL;
    struct addrinfo hints;
    struct addrinfo *result = NULL;
    struct sockaddr_in  *sockaddr_ipv4;

    char hostname[NI_MAXHOST]; //主機名稱
    char servInfo[NI_MAXSERV]; //具體連接成功的端口

    getnameinfo((struct sockaddr *) &serverAddr,
        sizeof(struct sockaddr),
        hostname,
        NI_MAXHOST, servInfo, NI_MAXSERV, NI_NUMERICSERV);

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    getaddrinfo(hostname, servInfo, &hints, &result);
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
    
        switch (ptr->ai_family) {
        case AF_UNSPEC:
            printf("Unspecified\n");
            break;
        case AF_INET:
            printf("AF_INET (IPv4)\n");
            sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
            printf("\tIPv4 address %s\n",
                inet_ntoa(sockaddr_ipv4->sin_addr));
            break;
        }
    
    }
    ///////////////////////////////////////////////////////////////////



    // 6.1 發送數據 send
    char buf[100] = "hello socket client,from server!";
    re = send(sToClientSock, buf, strlen(buf), 0);
    if (re == SOCKET_ERROR)
    {
        goto over;
    }
    // 6.2 接收數據  recv
    re = recv(sToClientSock, buf, sizeof(buf), 0);
    if (re == INVALID_SOCKET)
    {
        goto over;
    }
over:
    // 7. 關閉套接字     closesocket
    closesocket(listenSock);
    closesocket(sToClientSock);
    // 8. 清理環境      wsacleanup
    WSACleanup();

    return 0;
}

【網絡編程】使用getnameinfo()/getaddrinfo()/InetPton()