我正在C中创build一个简单的服务器。现在我无法创build套接字来侦听传入的连接。 我在一个运行在VirtualBox内的x86 Debian发行版上。 我的代码如下:
#define _POSIX_SOURCE #include <stdio.h> #include <pthread.h> /* threads, yo */ #include <stdlib.h> #include <memory.h> /* memset */ #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netdb.h> #include <arpa/inet.h> /* helpers like inet_ntop */ #include <netinet/in.h> void listenInput(); void* handleConn(void* args) { printf("Handling connection!\n"); listenInput(); return NULL; } void acceptData(int socket) { } void listenInput() { struct addrinfo hints; struct addrinfo *sockadr; char ipstr[INET6_ADDRSTRLEN]; int status; struct addrinfo *p = sockadr; int s; int yes = 1; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; printf("Getting addr info. Preparing to listen on port 8080\n"); if((status = getaddrinfo(NULL, "8080", &hints, &sockadr)) != 0) { printf("getaddrinfo: %s\n", gai_strerror(status)); return; } printf("Woo, got addr info!\n"); printf("Calling socket(...)\n"); if( -1 == (s = socket(p->ai_family, p->ai_socktype, p->ai_protocol))) { printf("Error creating socket (%d): %s\n", errno, gai_strerror(errno)); return; } printf("Calling bind\n"); bind(s, p->ai_addr, p->ai_addrlen); printf("Calling listen...\n"); listen(s, 5); { struct sockaddr_storage their_addr; socklen_t addr_size = sizeof their_addr; printf("accept()...\n"); int newsocket = accept(s, (struct sockaddr *)&their_addr, &addr_size); printf("Got a connection! New socket: %d\n", newsocket); } close(s); freeaddrinfo(sockadr); } int main(int argc, char** argv) { pthread_t thread; void* status; pthread_create(&thread, NULL, handleConn, NULL); pthread_join(thread, &status); printf("Joined thread!\n"); return 0; }
运行时, socket()
失败,错误代码为97 – 地址族不受支持。 到目前为止,我还没有find有关这个问题的相关信息。
这里是我的虚拟机中的ifconfig
的输出:
eth0 Link encap:Ethernet HWaddr 08:00:27:11:84:ee
inet addr:192.168.56.101 Bcast:192.168.56.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe11:84ee/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:122 errors:0 dropped:0 overruns:0 frame:0 TX packets:104 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:17778 (17.3 KiB) TX bytes:14571 (14.2 KiB)
链路封装:本地环回
inet addr:127.0.0.1掩码:255.0.0.0 inet6 addr:1/128范围:主机UP LOOPBACK RUNNING MTU:16436度量标准:1 RX包:64个错误:0丢弃:0超限:0帧:0 TX包: 64错误:0丢弃:0超载:0载波:0冲突:0 txqueuelen:0 RX字节:4652(4.5 KiB)TX字节:4652(4.5 KiB)
此外, netstat --tcp
显示其他stream套接字侦听,所以其他应用程序似乎成功创build它们。
问题是你的getaddrinfo()调用稍微不正确。
你设置指针* p:
p = sockadr;
getaddrinfo()作为最后一个参数传入&sockadr :
status = getaddrinfo(NULL, "8080", &hints, &sockadr)
你在调用socket()和bind()时使用sockadr的 旧值(通过p )
请注意: &sockadr是指向指针的指针,所以它可以将地址sockadr点改为。 而这正是发生的事情。 如果您在getaddrinfo()之前和之后将sockadr作为指针打印, 则会看到:
getaddrinfo()之前的sockadr:0x7fef07d8fee2
获取地址信息。 准备听8080端口
getaddrinfo()之后的sockadr:0x7fef000008c0
所以,可能的解决方案是在getaddrinfo()调用之后添加此行:
p = sockadr;
有关使用示例,请参阅man 3 getaddrinfo
。
PS。 我喜欢你的代码。 这是干净的,几乎是正确的。