简体   繁体   English

Mac OS X上的C插槽

[英]C Sockets on Mac OS X

Im trying to use sockets with C. Now Im writing server side software. 我正在尝试将套接字与C一起使用。现在我正在编写服务器端软件。 My new connection handler: 我的新连接处理程序:

int handle_new_connection(SOCKET *server_socket_descriptor, unsigned int *max_known_socket_descriptor, fd_set *main_socket_set)
{
    const int yes = 1;

    struct sockaddr_in remote_address;
    SOCKET new_connection_socket_descriptor;
    int address_size;
    char buffer[1000] = {0};
    struct hostent *host_entry;

    address_size = sizeof(struct sockaddr_in);

    if (SOCKET_ERROR == (new_connection_socket_descriptor = accept((*server_socket_descriptor), (struct sockaddr *)&remote_address, (socklen_t *)&address_size)))
    {
        return SOCKET_ERROR;
    }

    if ( SOCKET_ERROR == setsockopt(new_connection_socket_descriptor, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)))
    {
        return SOCKET_ERROR;
    }

    printf ("Server: new connection from \'%s\' accepted successfully.\n", inet_ntoa(remote_address.sin_addr));

    unsigned long remote_address_size = sizeof(remote_address.sin_addr);

    if (NULL == (host_entry = gethostbyaddr((void *)&(remote_address.sin_addr), (socklen_t)&(remote_address_size), AF_INET)))
    {
        closesocket (new_connection_socket_descriptor);
        printf ("Server: new connection from \'%s\' was immediately closed because of gethostbyaddr() failure.\n", host_entry -> h_addr);
        return SOCKET_ERROR;
    }

    printf("Been here!\n");


    return 1;
}

When new user connects (via telnet) if sentence if (NULL == (host_entry = gethostbyaddr((void *)&(remote_address.sin_addr), (socklen_t)&(remote_address_size), AF_INET))) brings error: Segmentation fault: 11 . 当新用户通过telnet连接时, if句子if (NULL == (host_entry = gethostbyaddr((void *)&(remote_address.sin_addr), (socklen_t)&(remote_address_size), AF_INET)))带来错误: Segmentation fault: 11 Also, this code works perfectly on Linux. 另外,此代码在Linux上也能完美运行。 My operating system is Mac OS X. How to solve this issue? 我的操作系统是Mac OSX。如何解决此问题?

You are passing the address of remote_address_size as the len parameter of gethostbyaddr() . 您正在将remote_address_size的地址作为gethostbyaddr()len参数传递。 That parameter should not be an address, just a length value, directly. 该参数不应直接是地址,而应是长度值。


Update: 更新:

Also, you may not be getting a struct sockaddr_in from accept() . 另外,您可能不会从accept()获得struct sockaddr_in For example, if the connection is an IPv6 connection, you would get a struct sockaddr_in6 . 例如,如果连接是IPv6连接,则将获得struct sockaddr_in6 The safest approach would be to use a struct sockaddr_storage . 最安全的方法是使用struct sockaddr_storage

Ideally, you should switch from gethostbyaddr() to getnameinfo() . 理想情况下,您应该从gethostbyaddr()切换到getnameinfo() The latter takes a struct sockaddr* argument, to which you can supply the pointer to your struct sockaddr_storage without having to care about what address family it actually contains. 后者采用struct sockaddr*参数,您可以向其提供指向struct sockaddr_storage的指针,而不必关心它实际包含的地址族。 The man page has sample code. 手册页包含示例代码。

If you want to keep using gethostbyaddr() , you will need to examine the sa_family field of the struct sockaddr_storage . 如果要继续使用gethostbyaddr() ,则需要检查struct sockaddr_storagesa_family字段。 If it's AF_INET , you should use &((struct sockaddr_in*)&remote_address)->sin_addr as the first argument. 如果是AF_INET ,则应使用&((struct sockaddr_in*)&remote_address)->sin_addr作为第一个参数。 If it's AF_INET6 , you should use &((struct sockaddr_in6*)&remote_address)->sin6_addr . 如果是AF_INET6 ,则应使用&((struct sockaddr_in6*)&remote_address)->sin6_addr The second argument would be the size of the same field. 第二个参数是相同字段的大小。

If the family is something else, you'll need to either look up how to handle that or return failure for a case not understood by your code. 如果是其他家庭,则需要查找如何处理该问题,或者针对代码无法理解的情况返回失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM