成功的socket(),bind(),listen()与errno 88 ENOTSOCK成功后,accept()失败

时间:2016-12-02 11:14:37

标签: c sockets network-programming signals

尝试让我的简单FTP服务器运行。它在远程服务器上运行。使用cat /etc/*-release显示服务器正在运行CentOS Linux 7核心。

参考:http://pubs.opengroup.org/onlinepubs/9699919799/,具体来说:

  

指定使用socket()创建的套接字,已绑定到带有bind()的地址,并已成功调用listen()。

我的程序成功调用socketbindlisten - 然后accept在服务器上失败。在OSX 10.11.5上它可以正常工作(在评论几个标题后)。

我正在使用gcc -std=c11 ftserver.c -o ftserver进行远程编译。使用logging和stderr我从执行中得到以下内容,抛出exit(1)。

记录输出(编辑):

ftserver 30000   <-- start the server on port 30000
socket() succeeded with sockfd = 3
bind() succeeded with sockfd = 3
listen() succeeded with sockfd = 3
Server open on 30000
ERROR: Obtaining new socket descriptor with 
    sockfd = 0
    temp_sockfd = -1
    errno = 88

以下是程序入口点到抛出错误的行的代码。

int main (int argc, char *argv[]) {
if (argc != 2) {
    printf("Usage: ftserver <port number>\n");
    exit(1);
}

int port = atoi(argv[1]);
char client_hostname[STRING_LENGTH];
bzero(client_hostname, STRING_LENGTH);

// set up the server's socket
int sockfd;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
    fprintf(stderr, "[ ERROR ] :: main() :: Failure to assign sockfd");
    exit(1);
}
else {
    printf("socket() succeeded with sockfd = %d\n", sockfd);
}

// fill the client socket address struct
struct sockaddr_in addr_client;
addr_client.sin_family = AF_INET;
addr_client.sin_port = htons(port);
addr_client.sin_addr.s_addr = INADDR_ANY;
bzero(&(addr_client.sin_zero), 8);

if (bind(sockfd, (struct sockaddr*)&addr_client, sizeof(struct sockaddr)) == -1 ) {
    fprintf(stderr, "[ ERROR ] :: main() :: Failure to bind port %d. Please select another port\n", port);
    exit(1);
}
else {
    printf("bind() succeeded with sockfd = %d\n", sockfd);
}

if (listen(sockfd, QUEUE) == -1) {
    fprintf(stderr, "[ ERROR ] :: main() :: Failure to listen on port %d\n", port);
    exit(1);
}
else {
    printf("listen() succeeded with sockfd = %d\n", sockfd);
}

printf ("Server open on %d\n", port);

struct sigaction signal_action;
signal_action.sa_handler = kill_zombies;
sigemptyset(&signal_action.sa_mask);
signal_action.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &signal_action, NULL) == -1) {
    perror("sigaction");
    return 1;
}
else {
    printf("sigaction succeeded\n");
}

struct sockaddr_in addr_server;
int temp_sockfd;

while (1) {
    socklen_t sin_size = sizeof(struct sockaddr_in);

    // accept() is used to connection to a client
    if ((temp_sockfd = accept(sockfd, (struct sockaddr *)&addr_server, &sin_size)) == -1) {
                    fprintf(stderr, "ERROR: Obtaining new socket descriptor with \n\tsockfd = %d\n\ttemp_sockfd = %d\n\terrno = %d\n", sockfd, temp_sockfd, errno);

        exit(1);
    }
    else {
        printf("accept() succeeded\n");
    }
// more code that we never have the pleasure to exec

标题:

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <strings.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>

// includes for server (CentOS) errors
// comment these out to compile locally (OSX)
// fixes error: ‘WNOHANG’ undeclared
#include <sys/wait.h>

// fixes error: ‘SA_RESTART’ undeclared
#include <asm/signal.h>

1 个答案:

答案 0 :(得分:2)

从您显示的日志中

  

sockfd = 0

很明显,在listen()accept()的来电之间,FD sockfd会被覆盖(此处:0)。

这很可能是因为在某个地方或之前调用了未定义的行为。

后者很可能会将 完全初始化 struct sigaction传递给sigaction()

要解决此问题,请正确初始化struct sigaction,例如:

struct sigaction signal_action = {0};