2009-01-15 17 views
5

मैंने नीचे दिया गया कोड शामिल किया है। कार्यक्रम पोर्ट 8888 पर टेलनेट कनेक्शन स्वीकार करने के लिए माना जाता है और फिर प्रत्येक टेलनेट क्लाइंट से मतदान और संदेश भेजकर और भेजता है लेकिन यह 100% काम नहीं करता है। ऐसा लगता है कि कुछ कनेक्शन हमेशा किसी को संदेश भेज सकते हैं और कार्यक्रम ठीक काम करता है लेकिन कम से कम एक ग्राहक होता है जो संदेश नहीं भेज सकता है। सभी ग्राहक हमेशा प्राप्त कर सकते हैं। (सर्वेक्षण आने वाले डेटा को पंजीकृत नहीं करता है)मेरा सरल सर्वेक्षण() उदाहरण केवल आंशिक रूप से काम करता है

यह कोड अपने आप पर चलता है, इसलिए यदि आप इसे फ़ाइल में डालते हैं और इसे gcc -o app filename.c के साथ संकलित करते हैं तो आप पोर्ट 8888 पर लोकहोस्ट को टेलनेट कर सकते हैं और इसे देख सकते हैं काम नहीं कर रहा। :-(इस कोड को फेडोरा के लिए लिखा गया था, लेकिन यह कुछ भी गैर linux विशिष्ट नहीं होना चाहिए। किसी भी मदद वास्तव में सराहना की जाएगी।

#include <stdio.h> 
#include <stdlib.h> 
#include <poll.h> 
#include <unistd.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <string.h> 
#include <signal.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <errno.h> 

#define PORT 8888 
#define MAX_CONN 10 
#define SECOND 1000 
#define TIMEOUT (30 * SECOND) 

static int listen_socket(); 

int main(int argc, char **argv) 
{ 
    struct pollfd **my_fds;     //array of pollfd structures for poll() 
    struct pollfd *curr, *new_conn;   //so I can loop through 
    int num_fds;        //count of how many are being used 
    int i, j;        //for loops 
    char buff[255], buff2[255];    //for sending and recieving text 
    struct sockaddr_in my_addr, their_addr; // my address information 
    socklen_t sin_size; 
    int buff_sz;        //size of data recieved 

    printf("App Started\n"); 

    //allocate space for 10 
    my_fds = (struct pollfd**) malloc(sizeof(struct pollfd*) * MAX_CONN); 

    //set all the pointers to NULL 
    for (i = 0; i < MAX_CONN; i++) 
     *(my_fds + i) = NULL; 

    //I call listen_socket() which creates a socket to listen to 
    //this is anchored into my_fds array at element 0. 
    curr = (struct pollfd*) malloc (sizeof(struct pollfd)); 
    curr->fd = listen_socket(); 
    curr->events = POLLIN; 
    curr->revents = 0; 

    *my_fds = curr; 

    printf("Listening socket fd locked always at position zero in array: %d\n", curr->fd); 

    //num_fds, the count of items in the array is set to 1 
    //because the listen socket is already present 
    num_fds = 1; 

    //This is the main loop. 
    //While (true) 
    // set all struct pollfd items revents to 0 
    // call poll 
    // loop through, see if there is data to read 
    //  read the data 
    //   loop through all sockets (except the listen_socket()) and send the data. 
    while (1) 
    { 

     //reset all event flag 
     for (i = 1; i < num_fds; i++) 
     { 
      curr = *(my_fds + i); 
      curr->events = POLLIN | POLLPRI; 
      printf("%i: fd %i\n", i, curr->fd); 
      curr->revents = 0; 
      send(curr->fd, "Enter some text:\n", 18, 0); 
     } 

     //put all this into poll and wait for something magical to happen 
     printf("calling poll (%d sockets)\n", num_fds); 
     if (poll(*my_fds, num_fds, TIMEOUT) == -1) 
     { 
      perror("poll"); 
      exit(0); 
     } 

     printf("poll returned!\n"); 

     //First item is the accepting socket....check it independently of the rest! 
     curr = *my_fds; 
     if (curr->revents != 0) 
     { 
      printf("We have a new connection.\nAccept goes here...\n"); 

      //Accept the connection 
      sin_size = sizeof their_addr; 
      new_conn = (struct pollfd*) malloc(sizeof(struct pollfd)); 
      new_conn->fd = accept(curr->fd, (struct sockaddr *)&their_addr, &sin_size); 
      new_conn->events = POLLIN; 
      new_conn->revents = 0; 

      printf("Connection from %s\n", inet_ntoa(their_addr.sin_addr)); 
      sprintf(buff, "Your %i\n", num_fds); 
      send(new_conn->fd, buff, 7, 0); 

      //Add it to the poll call 
      *(my_fds + num_fds) = new_conn; 
      num_fds++; 

     } 
     else 
     { 
      //skip first one, we know that's the accepting socket (handled above). 
      for (i = 1; i < num_fds; i++) 
      { 
       curr = *(my_fds + i); 
       if (curr->revents != 0) 
       { 
        buff_sz = recv(curr->fd, &buff, 254, 0); 
        buff[buff_sz] = '\0'; 
        printf("Recieved: %s", buff); 

        //send the message to everyone else 
        for (j = 1; j < num_fds; j++) 
        { 
         printf("i = %i, j = %i\n", i, j); 
         if (j != i) 
         { 
          new_conn = *(my_fds + j); 
          sprintf(buff2, "%i sent you %i: %s", i, j, buff); 
          send(new_conn->fd, buff2, strlen(buff2) + 1, 0); 
         } 
        } 
       } 
      } 
     } 
    } 

    printf("App Ended\n"); 
} 

static int listen_socket() 
{ 
    struct sockaddr_in a; 
    int s; 
    int yes; 

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
     perror("socket"); 
     return -1; 
    } 
    yes = 1; 
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 
      (char *) &yes, sizeof(yes)) < 0) { 
     perror("setsockopt"); 
     close(s); 
     return -1; 
    } 
    memset(&a, 0, sizeof(a)); 
    a.sin_port = htons(PORT); 
    a.sin_family = AF_INET; 
    if (bind(s, (struct sockaddr *) &a, sizeof(a)) < 0) { 
     perror("bind"); 
     close(s); 
     return -1; 
    } 
    printf("Accepting connections on port %d\n", PORT); 
    listen(s, 10); 
    return s; 
} 

उत्तर

11

चाहिए पोल नहीं है संरचनाओं की एक सरणी लेने के लिए? आदमी से पेज:

int poll(struct pollfd fds[], nfds_t nfds, int timeout); 

और तुम संरचनाओं की ओर इशारा की एक सरणी से गुजर रहे हैं:

struct pollfd **my_fds; 

मैं तुम्हें

की आवश्यकता है लगता है
struct pollfd *my_fds = calloc(sizeof(pollfd), MAX_CONN); 

फिर आपके कोड को काम करने का मौका मिला है।

+1

मुझे लगता है कि मैं इसे केवल ढेर पर आवंटित करूंगा, व्यक्तिगत रूप से ... struct pollfd my_fds [MAX_CONN]; –

+0

आकारों पर निर्भर करता है ... – Arkadiy

+0

सच है, लेकिन इस मामले में वे फ़ाइल डिस्क्रिप्टर हैं, इसलिए यह मानना ​​बहुत सुरक्षित है कि MAX_CONN उस बड़े होने वाला नहीं है। –