2017-07-08 4 views
0

Ich erstelle einen einfachen TCP-Echo-Server in c mit epoll. Beim Kompilieren gibt es Fehler: Socket operation on non-socketTCP-Server mit Epoll gibt Nicht-Socket-Fehler

warum gibt es non-socket? Ich habe es versucht, konnte mich aber nicht darum kümmern. unten ist mein Code und hier ist die article that i am following

mein Code:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <fcntl.h> 
#include <sys/epoll.h> 
#include <errno.h> 
#include <unistd.h> 
#define MAX_LISTEN_BACKLOG 1 
#define BUFFER_SIZE 4096 


int bind_and_create(char *port){ 
    struct addrinfo hints; 
    struct addrinfo *result, *rp; 
    int s, sfd; 

    memset(&hints, 0, sizeof(struct addrinfo)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 

    s = getaddrinfo(NULL, port , &hints, &result); 
    if(s != 0){ 
     fprintf(stderr,"getaddrinfo :%s\n",gai_strerror(s)); 
     return -1; 
    } 

    for(rp = result; rp!= NULL; rp->ai_next){ 
      int sfd = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol); 
     if (sfd == -1) 
      continue; 
     s = bind(sfd, rp->ai_addr,rp->ai_addrlen); 
     if (s == 0){ 
      //succefull managed to bind socket 
     break; 
     } 

      close(sfd); 
     } 

    if (rp == NULL){ 
     fprintf(stderr,"could not bind"); 
    } 
    freeaddrinfo(result); 
    return sfd; 
    } 


int make_socket_non_blocking(int sfd){ 

    int flags , s; 
    flags = fcntl(sfd, F_GETFL, 0); 
    if (flags == -1){ 
     perror("fnctl error"); 
     return -1; 
    } 

    flags |= O_NONBLOCK; 
    s = fcntl(sfd,F_SETFL,flags); 
    if (s == -1){ 
     perror("fnctl error"); 
     return -1; 
    } 
    return 0; 
} 


#define MAXEVENTS 64 

int main (int argc, char *argv[]) 
{ 
    int sfd, s; 
    int efd; 
    struct epoll_event event; 
    struct epoll_event *events; 

    if (argc != 2) 
    { 
     fprintf (stderr, "Usage: %s [port]\n", argv[0]); 
     exit (EXIT_FAILURE); 
    } 

    sfd = bind_and_create (argv[1]); 
    if (sfd == -1) 
    abort(); 

    s = make_socket_non_blocking (sfd); 
    if (s == -1) 
    abort(); 

    s = listen (sfd, SOMAXCONN); // error is here but why???? 
    if (s == -1) 
    { 
     perror ("listen"); 
     abort(); 
    } 

    efd = epoll_create1 (0); 
    if (efd == -1) 
    { 
     perror ("epoll_create"); 
     abort(); 
    } 

    event.data.fd = sfd; 
    event.events = EPOLLIN | EPOLLET; 
    s = epoll_ctl (efd, EPOLL_CTL_ADD, sfd, &event); 
    if (s == -1) 
    { 
     perror ("epoll_ctl"); 
     abort(); 
    } 

    /* Buffer where events are returned */ 
    events = calloc (MAXEVENTS, sizeof event); 

    /* The event loop */ 
    while (1) 
    { 
     int n, i; 

     n = epoll_wait (efd, events, MAXEVENTS, -1); 
     for (i = 0; i < n; i++) 
    { 
     if ((events[i].events & EPOLLERR) || 
       (events[i].events & EPOLLHUP) || 
       (!(events[i].events & EPOLLIN))) 
     { 
       /* An error has occured on this fd, or the socket is not 
       ready for reading (why were we notified then?) */ 
      fprintf (stderr, "epoll error\n"); 
      close (events[i].data.fd); 
      continue; 
     } 

     else if (sfd == events[i].data.fd) 
     { 
       /* We have a notification on the listening socket, which 
       means one or more incoming connections. */ 
       while (1) 
       { 
        struct sockaddr in_addr; 
        socklen_t in_len; 
        int infd; 
        char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; 

        in_len = sizeof in_addr; 
        infd = accept (sfd, &in_addr, &in_len); 
        if (infd == -1) 
        { 
         if ((errno == EAGAIN) || 
          (errno == EWOULDBLOCK)) 
         { 
          /* We have processed all incoming 
          connections. */ 
          break; 
         } 
         else 
         { 
          perror ("accept"); 
          break; 
         } 
        } 

        s = getnameinfo (&in_addr, in_len, 
            hbuf, sizeof hbuf, 
            sbuf, sizeof sbuf, 
            NI_NUMERICHOST | NI_NUMERICSERV); 
        if (s == 0) 
        { 
         printf("Accepted connection on descriptor %d " 
          "(host=%s, port=%s)\n", infd, hbuf, sbuf); 
        } 

        /* Make the incoming socket non-blocking and add it to the 
        list of fds to monitor. */ 
        s = make_socket_non_blocking (infd); 
        if (s == -1) 
        abort(); 

        event.data.fd = infd; 
        event.events = EPOLLIN | EPOLLET; 
        s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); 
        if (s == -1) 
        { 
         perror ("epoll_ctl"); 
         abort(); 
        } 
       } 
       continue; 
      } 
      else 
      { 
       /* We have data on the fd waiting to be read. Read and 
       display it. We must read whatever data is available 
       completely, as we are running in edge-triggered mode 
       and won't get a notification again for the same 
       data. */ 
       int done = 0; 

       while (1) 
       { 
        ssize_t count; 
        char buf[512]; 

        count = read (events[i].data.fd, buf, sizeof buf); 
        if (count == -1) 
        { 
         /* If errno == EAGAIN, that means we have read all 
         data. So go back to the main loop. */ 
         if (errno != EAGAIN) 
         { 
          perror ("read"); 
          done = 1; 
         } 
         break; 
        } 
        else if (count == 0) 
        { 
         /* End of file. The remote has closed the 
         connection. */ 
         done = 1; 
         break; 
        } 

        /* Write the buffer to standard output */ 
        s = write (1, buf, count); 
        if (s == -1) 
        { 
         perror ("write"); 
         abort(); 
        } 
       } 

       if (done) 
       { 
        printf ("Closed connection on descriptor %d\n", 
          events[i].data.fd); 

        /* Closing the descriptor will make epoll remove it 
        from the set of descriptors which are monitored. */ 
        close (events[i].data.fd); 
       } 
      } 
     } 
    } 

    free (events); 

    close (sfd); 

    return EXIT_SUCCESS; 
} 

Antwort

1
int bind_and_create(char *port){ 
    ... 
    int s, sfd; // <- one sfd 
    ... 
    for(rp = result; rp!= NULL; rp->ai_next){ // <- rp->ai_next has no effect 
     int sfd = socket(...); // <-- two sfd 
     ... 
     close(sfd); // <-- two sfd gone 
    } 
    ... 
    return sfd; // <-- one sfd, still completely uninitialised 
} 

Wenn Sie Ihre Zeit auf, dies stoppen wollen verschwenden, Verwendung -Wall oder ein äquivalentes Compiler Einstellung.

+0

danke ich jetzt verstanden und auch danke für die Erwähnung von '-Wall' wird es definitiv verwenden. – anekix

+0

auch warum ist 'rp-> ai_next' unbenutzt.ist da noch eine andere Art zu iterieren? – anekix

+0

'rp-> ai_next' ist ein Ausdruck. Sie möchten einen Zeiger ändern, um auf das nächste Listenelement zu zeigen, aber 'rp-> ai_next' ändert nichts. –

Verwandte Themen