2016-12-02 11 views
2

Попытка получить мой простой FTP-сервер. Он работает на удаленном сервере. Использование cat /etc/*-release показывает, что на сервере работает ядро ​​CentOS Linux 7.accept() сбой после успешного сокета(), bind(), listen() с errno 88 ENOTSOCK

Реферировано: http://pubs.opengroup.org/onlinepubs/9699919799/, а именно:

Определяет сокет, который был создан с гнездом(), был связан с адресом с Bind(), и выпустил успешный вызов слушать().

Моя программа успешно называет socket, bind и listen - тогда accept сбой на сервере. В OSX 10.11.5 он работает очень хорошо (после комментирования нескольких заголовков).

Я собираюсь удаленно с gcc -std=c11 ftserver.c -o ftserver. Используя logging и stderr, я получаю следующее от выполнения, чтобы он выбрал exit (1).

выход Logging (редактировать):

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

Errno 88 обычно указывает на работу сокетов о неприменении розеткой. Pls печатает значения sockfd после каждой операции, а также дважды проверяет, не мешаете ли вы с ним в другом месте. – Jay

+2

'if (bind (sockfd, (struct sockaddr *) & addr_client, sizeof (struct sockaddr)) == -1)' Я думаю, что это должно быть 'sizeof sockaddr_in' или' sizeof addr_client' –

+0

@Jay - я обновил свой должность в двух местах. Один из них - это вывод журнала с указанными значениями 'sockfd'. Второй - это код, который делает вывод (согласованность eh?). Вышеупомянутый код является точкой входа в программу, ничего не вызывается или не выполняется до того, что я опубликовал. – FearJoy

ответ

2

Из бревен вы показываете

sockfd = 0

, очевидно, что между вызовами listen() и accept() ФД sockfd переписывается en (здесь: до 0).

Это скорее всего связано с неопределенным поведением, которое вызывается где-то тогда или раньше.

Последние, скорее всего, сборы на прохождение не полностью инициализируетсяstruct sigaction к sigaction().

Чтобы исправить это, правильно инициализацию struct sigaction, например так:

struct sigaction signal_action = {0}; 

 Смежные вопросы

  • Нет связанных вопросов^_^