【问题标题】:connect() giving error in UDP client server for IPv6 address in C windowsconnect() 在 C windows 中的 IPv6 地址的 UDP 客户端服务器中给出错误
【发布时间】:2015-12-31 06:44:52
【问题描述】:

在这里,我尝试在 Windows 中使用 IPV6 地址从服务器发送和接收数据。在客户端代码中,我没有获取服务器的地址来发送数据或接收数据。在测试我的代码时,我发现客户端代码中的 Connect() 给出了运行时错误。我可能无法正确复制 memmove() 中的地址。实际上,在客户端代码中,我尝试使用 gethostbyaddr() 但仍然无法发送或接收数据。请帮帮我。那我如何连接到服务器...还发送和接收数据..提前谢谢

*/客户端代码 Udp_win_IP6_Client.c/*

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>   
#pragma comment(lib,"ws2_32.lib")    
int main() {
    struct sockaddr_in6 client6;
    WORD wVersionRequested;
    int wsaerr;
    socklen_t size;
    struct hostent *server;
    WSADATA wsaData;
    char buffer[1024] = "Hi Harshpal Server";   
    int k;
    printf("\n Ready for Sending...\n");
    wVersionRequested = MAKEWORD(2, 2);
    wsaerr = WSAStartup(wVersionRequested, &wsaData);
    SOCKET clientsockfd;
    clientsockfd = socket(AF_INET6, SOCK_DGRAM, 0);
    if (clientsockfd == INVALID_SOCKET)
        printf("\n Error.... ");
    else
        printf("\n Successful Creation....");

    server = gethostbyname("::1");
    if(server < 0)
        printf("\n Couldnt get hostname");
    else
        printf("\n Got the hostname");

    memset((char *) &client6, 0, sizeof (client6));
    printf("\n Memory set \n");
    client6.sin6_flowinfo = 0;
    client6.sin6_family = AF_INET6;            
    memmove((char *) &client6.sin6_addr.s6_addr, (char *)server->h_name, server->h_length);
    client6.sin6_port = htons(5000);

    size = sizeof client6;
   if (connect(clientsockfd, (struct sockaddr *) &client6, sizeof (client6)) == SOCKET_ERROR)
        printf("ERROR connecting");
   else
        printf("Connected...");
    printf("Type a sentence to send to server:\n");
    scanf("%s", buffer);
    printf("You typed: %s\n", buffer);

    int n = send(clientsockfd, buffer, strlen(buffer) + 1, 0);
    sendto(clientsockfd, buffer, n, 0, (struct sockaddr *) &client6, size);

    memset(buffer, 0, 1024);
    n = recvfrom(clientsockfd, buffer, 1024, 0, NULL, NULL);    
    printf("This is Message Received from server: %s\n", buffer);
    closesocket(clientsockfd);    
    return 0;
}

*/*服务器端代码 Udp_win_IP6_Server.c /

 #include <stdio.h>
    #include <stdlib.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #pragma comment(lib,"ws2_32.lib")

int main() {
    WORD wVersionRequested;
    int wsaerr;
    WSADATA wsaData;
    char buffer[1024];
    int k;
    printf("\n Ready for Receiving...\n");
    wVersionRequested = MAKEWORD(2, 2);    
    wsaerr = WSAStartup(wVersionRequested, &wsaData);

    SOCKET sockfd;
    sockfd = socket(AF_INET6, SOCK_DGRAM, 0);

    if(sockfd == INVALID_SOCKET)
        printf("\n Error.... ");    
    else
        printf("\n Successful Creation....");      
    struct sockaddr_in6 server6;
    memset(&server6, 0, sizeof (server6));
    server6.sin6_family = AF_INET6;
    server6.sin6_addr = in6addr_any;
    server6.sin6_port = htons(5000);

    if(bind(sockfd, (struct sockaddr *)&server6 , sizeof(server6))==-1)
    {
        printf("\n Error in binding..\n");       
    }
    else{
        printf("\n Binding successful...\n");
    }
    k = sizeof(server6);

    recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *) &server6, &k);     
    printf("\n Message from client %s: ", buffer);

    strcpy(buffer,"Hi Harshpal Client...");
    sendto(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*) &server6,k);
    closesocket(sockfd);
    return 0;
}
  • 直接使用gcc运行代码 Udp_win_IP6_Server.c -o Udp_win_IP6_Server.o
  • 和 gcc Udp_win_IP6_Client.c -o Udp_win_IP6_Client.o
  • 或者您可以在任何 IDE 中运行。
  • 运行代码时无需指定地址或端口,正如我在代码中给出的那样。

【问题讨论】:

  • 发布的代码似乎缺少#include 语句:&lt;sys/types.h&gt;&lt;sys/socket.h&gt;&lt;string.h&gt;&lt;arpa/inet.h&gt;
  • 那些对gcc 的调用将编译/链接代码,它们不会运行代码
  • 警告:我对 ipv6 不太熟悉。关于这一行:server = gethostbyname("::1"); 通常参数类似于:"google.com" 通常域名是用于参数的 char 字符串的内容
  • @user3629249 感谢您的回复...您提到的那些头文件..我猜它只在 linux 上运行...如果我包含它会出错。我希望此代码仅在 Windows 上运行。而且我也对 server = gethostbyname("::1")....我尝试使用 gethostbyaddr...但没有任何变化... :-(
  • 你知道你要连接的服务器的域名吗?如果是这样,那么这就是我将用作gethostbyname() 的参数

标签: c windows sockets gcc


【解决方案1】:

我相信if (server &lt; 0) 检查是不正确的,因为server 是一个指针,因此是无符号的。只需检查是否为NULLgethostbyname() 也已被弃用,但让其用于示例代码。

Memmove 部分似乎也有问题。您需要从h_addr_list 获取解析地址,而不是从h_name。所以你的client6初始化应该是:

struct sockaddr_in6 client6;
memset(&client6, 0, sizeof(client6));
client6.sin6_family = AF_INET6;
client6.sin6_port = htons(5000);
memcpy(&client6.sin6_addr, server->h_addr_list[0], server->h_length);

【讨论】:

  • 感谢您的回复...我已经按照您在此处所说的进行了尝试,但 server 的值仍然存在错误。我检查了 if(server == NULL)...它说“无法获取主机名”,我不明白为什么服务器不使用函数 gethostbyname(::1) 存储主机数据;我收到此错误“收到的信号:SIGSEGV(分段错误)”
  • 从你的问题中并不清楚你在那里得到了错误,我以为你在connect() 电话之后得到它。当然,在取消引用memcpy 中的 NULL 指针时会出现段错误。我建议您使用 getaddrinfo() 而不是 gethostbyname(),因为它已弃用并且无法正确解析 IPv6 地址字符串(仅支持 IPv6 主机名)。
  • 或者您可以使用inet_pton 将“::1”解析为地址。但它不支持域名,所以我会选择getaddrinfo
  • 实际上在 Linux 中我使用过server = gethostbyname2("::1", AF_INET6);,这段代码运行良好。此 UDP_SERVER 代码同时支持 IP4 和 IP6。但是在windows中没有像gethostbyname2这样的功能......所以这是一个问题......现在我仍然遇到这个问题......我也不知道为什么windows不支持inet_pton。为了解析“::1”,我输入了“localhost”,但我猜它使用的是127.0.0.1而不是IP6……但事实是我想在windows中运行这段代码而不改变structure,这是getaddrinfo所需要的
  • Windows 确实支持 inet_pton(作为 ANSI inet_pton 和特定于 WSA 的 InetPton),但不支持 gethostbyname2。这就是为什么你最好使用getaddrinfo,这在 Windows 和 Linux 上是一样的。
【解决方案2】:

我刚刚得到了答案....这是我的代码...很高兴与您分享.....保持 Server.c 不变,仅用以下代码替换 client.c :-)

#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <mstcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
int main() {

    char Buffer[1024] = "This is Client \n";
    char FromServerBuffer[1024];
    char hostname[1024];

    SOCKADDR_STORAGE From;
    WSADATA wsaData;
    ADDRINFO Hints, *AddInf, *AI;
    int RetVal, gaddr, i;
    LPSOCKADDR sockaddr_ip;

    WSAStartup(MAKEWORD(2, 2), &wsaData);
    // Intializing dll required..
    memset(&Hints, 0, sizeof (Hints));

    char ipstringbuffer[50];
    DWORD ipbufferlength = 50;

    SOCKET ConnSocket;
    Hints.ai_family = PF_UNSPEC;
    Hints.ai_socktype = SOCK_DGRAM;
    Hints.ai_flags = AI_PASSIVE;
    // Setting family, socktype and flag.
    gaddr = getaddrinfo("::1", "5000", &Hints, &AddInf);
    // getaddrinfo() will give information about address.

    for (AI = AddInf; AI != NULL; AI = AI->ai_next) {
        sockaddr_ip = (LPSOCKADDR) AI->ai_addr;
        // This loop to place IP and port into the list of IP addresses.
        int iRetval = WSAAddressToString(sockaddr_ip, (DWORD) AI->ai_addrlen, NULL, ipstringbuffer, &ipbufferlength);
        // Convert address in readable format..
        printf("\tIPv6 address %s\n", ipstringbuffer);

        ConnSocket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
        // Creating Socket...
        if (ConnSocket == INVALID_SOCKET)
            printf("socket call failed.. \n");

        if (connect(ConnSocket, AI->ai_addr, (int) AI->ai_addrlen) != SOCKET_ERROR) {
            // Connecting client socket to server..
            printf("Connection Establish..\n");
        } else
            printf("Connection not establish..");

        int FromLen = sizeof (From);
        RetVal = send(ConnSocket, Buffer, sizeof (Buffer), 0);
        // Sending data to server using send().
        //RetVal = sendto(ConnSocket, Buffer, sizeof (Buffer), 0, (LPSOCKADDR) & From, FromLen);
        if (RetVal < 0) {
            printf("Sending failed..\n");

        } else
            printf("Sending Successful..\n");

        int AmountRead = recvfrom(ConnSocket, FromServerBuffer, sizeof (FromServerBuffer), 0, (LPSOCKADDR) & From, &FromLen);
        // Receiving data using recvfrom..
        printf("Data Received From Server: %s", FromServerBuffer);

    }
    closesocket(ConnSocket);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-16
    • 2017-03-29
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多