C problem z connect()

Odpowiedz Nowy wątek
2011-08-23 18:11
Newb
0

Witam,
Jestem w trakcie pisania prostego serwera chatu, aby nauczyć się programowania gniazd w systemach zgodnych z POSIX (nic związanego z uczelnią, by lepiej poznać C i Uniksa). W pewnym momencie spowodowałem błąd i od tej pory klient nie łączy się z serwerem. Jestem pewny, że używam właściwego portu oraz adresu IP.

Jeśli ktoś pyta po co klient na chwilę ma stać się serwerem? Po to aby serwer wysłał mu informacje trzymane w swoim kontenerze. Nastepnie zamyka serwerowe gniazdo.

Główny problem: connect call failed: Connection refused
Mam pewność, że aplikacja serwera jest aktywna w momencie, gdy klient próbuje połączyć się z serwerem.

  1. Dlaczego connection refused mimo że serwer nasłuchuje?
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
#include "config.h"
 
void usage(const char* argv1) {
  fprintf(stderr, "Need to create config file in user home directory: ~/.chatsrv/svr.conf\n");
  fprintf(stderr, "Check ~/.chatsvr/svr.conf.default\n");
  fprintf(stderr, "It is not a good idea to run this deamon as root!\n");
  fprintf(stderr, "Run '%s -D' to daemonize!\n", argv1);
  exit(0);
}
 
int main(int argc, char** argv)
{
 
  if ( ( argc == 2 && ( strcmp(argv[1], "--help") == 0 ) ) || argc > 2 )
    usage(argv[0]);
 
  /*
   *  Run in background
   */
  if(argc > 1 && ( strcmp(argv[1], "-D") == 0 ) ) {
    printf("Going background..\n");
    pid_t pid;
    switch( pid = fork() ) {
      case 0: // child
    break;
      default: // parent
    printf("Background %d\n", pid);
    return 0;
    }
  }
  /*
   *  Config loading.
   */
  init_directory();
  load_config();
 
  /*
   *  Container setup
   */ 
  msgroot* root = NULL;
  msglist* top = NULL;
  initialize_list(&root, &top);
 
  /*
   *  Run server
   */
  int sockfd, newsockfd;
  struct sockaddr_in server = {AF_INET, clientport, INADDR_ANY};
  // set the end point of the transport
  if( ( sockfd = socket(AF_INET, SOCK_STREAM, 0 )) == -1 ) {
    fprintf(stderr, "Socket call failed!\n");
    exit(1);
  }
  // bind server address with the end point
  if( bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    fprintf(stderr, "Bind call failed!\n");
    exit(1);
  }
  // listen
  if( listen(sockfd, 5) == -1 ) {
    fprintf(stderr, "Listen call failed!\n");
    exit(1);
  }
 
  msgbody tmp;
  struct sockaddr_in client;
  int len = sizeof(struct sockaddr_in);
  char buff[MAX_LINE];
  // proceed connection
  printf("Started accept loop..\n");
  while(1) {
    // accept for connections
    if( ( newsockfd = accept(sockfd, (struct sockaddr*) &client, &len)) == -1 ) {
      fprintf(stderr, "Accept call failed!\n");
      continue;
    }
 
    // log connection
    time_t time;
    FILE* fp;
    if( (fp = fopen(logpath, "a+")) == NULL  ) {
      fprintf(stderr, "Cannot open log file!\n");
      exit(1);
    }
    printf("Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fprintf(fp, "Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fclose(fp);
 
    // create child to proceed new connection
    if( fork() == 0 ) {
      // recieve data
      while( recv(newsockfd, &tmp, sizeof(msgbody), 0) > 0 ) {
    printf("Code: %d\n", tmp.code);
    /*
     * for code = -1 then send list of messages to the client
     */
    if(tmp.code == -1) {
      struct sockaddr_in client_server = {AF_INET, clientport};
      // server (of client application) address
      client_server.sin_addr.s_addr = client.sin_addr.s_addr;
      int sendsockd;
      // connect to client
      if( (sendsockd =  socket(AF_INET, SOCK_STREAM, 0) ) == -1 ) {
        fprintf(stderr, "Socket failed\n");
        exit(1);
      }
      // send container to client
      client_server.sin_addr = client.sin_addr;
      close(sendsockd);
    }
 
    if(tmp.code == 1) {
      // push message to container
      // while push set code = 0
      tmp.code = 0;
      push(root, &top, tmp);
      printf("Number of elements: %d\n", size(root));
      printf(ctime(&tmp.time));
      printf("%s: %s", tmp.name, tmp.msg);
    }
      }
    }
  }
 
  return 0;
}

Klient:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<time.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
 
int main(int argc, char** argv)
{ 
  /*
   * Basic client setup
   */
 
  /*
   * Container setup
   */
  msgroot* root = NULL;
  // top of the list
  msglist* top = NULL;
  initialize_list(&root, &top);
 
  /*
   * Connect to server
   */
  int sockfd, sockfdb;
  const int port = 4321;
  struct sockaddr_in server = {AF_INET, port};
  // convert and remember server address
  server.sin_addr.s_addr = inet_addr("10.0.0.5");
  // set the end point of transport
  if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
    perror("socket call failed");
    exit(1);
  }
  // connect socket with server address
  if ( connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    perror("connect call failed");
    exit(1);
  }
 
  /*
   *  Recieve data from server
   */
  msgbody tmp;
  int clientlisten = 25000;
  struct sockaddr_in tmpserver = {AF_INET, clientlisten, INADDR_ANY};
  // code = -1 - get list of messages from server
  tmp.code = -1;
  send(sockfd, &tmp, sizeof(msgbody), 0);
  if ( (sockfdb = socket(AF_INET, SOCK_STREAM, 0 )) == -1 ) {
    perror("socket call failed");
    exit(1);
  }
  if ( bind(sockfdb, (struct sockaddr*) &tmpserver, sizeof(struct sockaddr_in)) == -1 ) {
    perror("bind call failed");
    exit(1);
  }
 
  // there will be getting structures code
 
  close(sockfdb);
 
  /*
   *  Run client information sending.
   */ 
  time_t currenttime;
  char msgbuf[MSGSIZE];
  const char* name = "Author";
  while(1) {
    currenttime = time(NULL);
    // send information to server
    printf("Message: ");
    fgets(msgbuf, MSGSIZE - 1, stdin);
    strcpy(tmp.msg, msgbuf);
    strcpy(tmp.name, name);
    tmp.time = currenttime;
    // code 1 - normal message
    tmp.code = 1;
    send(sockfd, &tmp, sizeof(msgbody), 0);
  }
  close(sockfd);
  return 0;
}

Raczej w tym miesjcu kończy się kod, gdzie na 95% wydaje mi się, że jest błąd.

Pozostało 580 znaków

2011-08-23 18:17
Newb
0

Damn it, a jednak użyłem złego numeru portu. Dopiero za którymś razem to zauważyłem. Teraz widzę inny problem. Dzięki i sorry za zaśmiecenie.

Pozostało 580 znaków

2011-08-23 18:26
Kumashiro
0
Newb napisał(a)

Jeśli ktoś pyta po co klient na chwilę ma stać się serwerem? Po to aby serwer wysłał mu informacje trzymane w swoim kontenerze. Nastepnie zamyka serwerowe gniazdo.

Ojjj.... Nie analizowałem Twojego kodu (dużo czytania), ale ten pomysł jest conajmniej dziwny.
Są dwie metody łączności stanowej: klient-serwer i peer-to-peer. W pierwszym klient nigdy nie staje się serwerem, nawet na chwilę. W drugim coś takiego jak serwer nie istnieje (obie strony połączenia są równoważne, zaś kto do kogo będzie się łączył ustala kolejność lub inny mechanizm). Dopóki do powszechnego użycia nie wejdzie IPv6, ten drugi model trzeba stosować tylko w przypadku, gdy jest to uzasadnione. W przeciwnym stosuje się klient-serwer. Teraz, co zrobić jeśli serwer chce coś przesłać do klienta, ale nie wiemy kiedy to nastąpi i czy w ogóle będzie miało miejsce. Zasada jest prosta, klient łączy się z serwerem i utrzymuje połączenie (warto słać NOOPy co jakiś czas, bo niektóre firewalle są złośliwe). Zarówno klient jak i serwer sprawdzają czy druga strona nie ma przypadkiem czegoś do powiedzenia i w takim przypadku zaczyna nasłuchiwać. Jeśli chce coś wysłać, sprawdza czy druga strona może odbierać i wysyła. To wszystko. Klient nie musi otwierać gniazda serwerowego, gdyż komunikacja po jednym kanale jest dwukierunkowa.
Otwieranie portu po stronie klienta jest złym pomysłem, szczególnie w przypadku chatów. Zapewne klient będzie na desktopie, a ten może być skonfigurowany na odrzucanie wszelkich prób nawiązania połączenia z zewnątrz. Dodatkowo może być w sieci za NATem i nie jest widoczny od strony świata, zatem otwieranie portów nic nie da.
Zastanów się jeszcze raz nad swoją architekturą.

Pozostało 580 znaków

2011-08-23 21:39
Newb
0

Dzięki za zwrócenie uwagi. Poprawiłem kod, komunikacja ma się odbywać tylko na jednym porcie. Zastanawia mnie teraz następująca rzecz - dlaczego pętla otrzymywania wiadomości przez klienta jest nieskończona?

klient

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<time.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
 
int main(int argc, char** argv)
{ 
  /*
   * Basic client setup
   */
 
  /*
   * Container setup
   */
  msgroot* root = NULL;
  // top of the list
  msglist* top = NULL;
  initialize_list(&root, &top);
 
  /*
   * Connect to server
   */
  int sockfd;
  const int port = 4321;
  struct sockaddr_in server = {AF_INET, port};
  // convert and remember server address
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  // set the end point of transport
  if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
    perror("socket call failed");
    exit(1);
  }
  // connect socket with server address
  if ( connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    perror("connect call failed");
    exit(1);
  }
 
  msgbody tmp;
  /*
   *  Recieve data from server
   */
  tmp.code = -1; // -1 = get list
  send(sockfd, &tmp, sizeof(msgbody), 0);
  while( recv(sockfd, &tmp, sizeof(msgbody), 0) > 0 ) {
    printf("Got Message\n");
    printf("%s: %s\n", tmp.name, tmp.msg);
    push(root, &top, tmp);
  }
  printf("Reciving loop is not infinite!\n");
 
  /*
   *  Run client information sending.
   */ 
  time_t currenttime;
  char msgbuf[MSGSIZE];
  const char* name = "Author";
  while(1) {
    printf("Stared infinite loop\n");
    currenttime = time(NULL);
    // send information to server
    printf("Message: ");
    fgets(msgbuf, MSGSIZE - 1, stdin);
    strcpy(tmp.msg, msgbuf);
    strcpy(tmp.name, name);
    tmp.time = currenttime;
    // code 1 - normal message
    tmp.code = 1;
    send(sockfd, &tmp, sizeof(msgbody), 0);
  }
  close(sockfd);
  return 0;
}

Napis "Reciving loop is not infinite!\n" nigdy nie wyświetli się. Odebranie wiadomości nadanych przez serwer przebiega prawidłowo.

Poprawiony serwer

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
#include "config.h"
 
void usage(const char* argv1) {
  fprintf(stderr, "Need to create config file in user home directory: ~/.chatsrv/svr.conf\n");
  fprintf(stderr, "Check ~/.chatsvr/svr.conf.default\n");
  fprintf(stderr, "It is not a good idea to run this deamon as root!\n");
  fprintf(stderr, "Run '%s -D' to daemonize!\n", argv1);
  exit(0);
}
 
int main(int argc, char** argv)
{
 
  if ( ( argc == 2 && ( strcmp(argv[1], "--help") == 0 ) ) || argc > 2 )
    usage(argv[0]);
 
  /*
   *  Run in background
   */
  if(argc > 1 && ( strcmp(argv[1], "-D") == 0 ) ) {
    printf("Going background..\n");
    pid_t pid;
    switch( pid = fork() ) {
      case 0: // child
    break;
      default: // parent
    printf("Background %d\n", pid);
    return 0;
    }
  }
  /*
   *  Config loading.
   */
  init_directory();
  load_config();
 
  /*
   *  Container setup
   */ 
  msgroot* root = NULL;
  msglist* top = NULL;
  initialize_list(&root, &top);
  // push test messages
  msgbody tmp;
  strcpy(tmp.name, "Testowy autor");
  strcpy(tmp.msg, "Testowa wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);  
  strcpy(tmp.name, "autor");
  strcpy(tmp.msg, "wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);
  strcpy(tmp.name, "kolejny");
  strcpy(tmp.msg, "wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);
  /*
   *  Run server
   */
  int sockfd, newsockfd;
  struct sockaddr_in server = {AF_INET, serverport, INADDR_ANY};
  // set the end point of the transport
  if( ( sockfd = socket(AF_INET, SOCK_STREAM, 0 )) == -1 ) {
    fprintf(stderr, "Socket call failed!\n");
    exit(1);
  }
  // bind server address with the end point
  if( bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    fprintf(stderr, "Bind call failed!\n");
    exit(1);
  }
  // listen
  if( listen(sockfd, 5) == -1 ) {
    fprintf(stderr, "Listen call failed!\n");
    exit(1);
  }
 
  struct sockaddr_in client;
  int len = sizeof(struct sockaddr_in);
  char buff[MAX_LINE];
  // proceed connection
  printf("Started accept loop..\n");
  while(1) {
    // accept for connections
    if( ( newsockfd = accept(sockfd, (struct sockaddr*) &client, &len)) == -1 ) {
      fprintf(stderr, "Accept call failed!\n");
      continue;
    }
 
    // log connection
    FILE* fp;
    if( (fp = fopen(logpath, "a+")) == NULL  ) {
      fprintf(stderr, "Cannot open log file!\n");
      exit(1);
    }
    printf("Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fprintf(fp, "Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fclose(fp);
 
    // create child to proceed new connection
    if( fork() == 0 ) {
      // recieve data
      while( recv(newsockfd, &tmp, sizeof(msgbody), 0) > 0 ) {
    printf("Code: %d\n", tmp.code);
    /*
     * for code = -1 then send list of messages to the client
     */
    if(tmp.code == -1) {
      // display messages in the list
      if(root->first != NULL) {
        msglist* ptr = root->first;
        while(ptr != NULL) {
          printf("Sending..\n");
          printf("%s: %s\n", ptr->body.name, ptr->body.msg);
          send(newsockfd, &(ptr->body), sizeof(msgbody), 0);
          ptr = ptr->next;
        }
      }
    }
 
    if(tmp.code == 1) {
      // push message to container
      // while push set code = 0
      tmp.code = 0;
      push(root, &top, tmp);
      printf("Number of elements: %d\n", size(root));
      printf(ctime(&tmp.time));
      printf("%s: %s", tmp.name, tmp.msg);
    }
      }
    }
  }
 
  return 0;
}

Pozostało 580 znaków

2011-08-23 22:23
Kumashiro
0
Newb napisał(a)

Zastanawia mnie teraz następująca rzecz - dlaczego pętla otrzymywania wiadomości przez klienta jest nieskończona?

Wywołanie recv() jest blokujące!!! Dopóki z serwera otrzymujesz jakieś dane i w transmisji (którą i tak źle obsługujesz; poczytaj o protokołach strumieniowych) nie trafisz akurat na brak danych, to ta pętla się nie zakończy. Zerwanie połączenia przez serwer też ją zakończy.

Pozostało 580 znaków

2011-08-24 01:52
Newb
0

Jeżeli dobrze zrozumiałem, to obsługując gniazda domyślnie, czyli blokująco, pętla nigdy nie zakończy się. Czyli mój protokół jest odpowiedzialny za zakończenie pętli. Co innego w gniazdach nieblokujących, gdzie wszystko dzieje się asynchronicznie.

Wprowadziłem do mojego protokołu dodatkowo kod = -2, który ma służyć zakończeniu transmisji danych zmagazynowanych w serwerze. Kod wygląda teraz następująco:

klient

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<time.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
 
int main(int argc, char** argv)
{ 
  /*
   * Basic client setup
   */
 
  /*
   * Container setup
   */
  msgroot* root = NULL;
  // top of the list
  msglist* top = NULL;
  initialize_list(&root, &top);
 
  /*
   * Connect to server
   */
  int sockfd;
  const int port = 4321;
  struct sockaddr_in server = {AF_INET, port};
  // convert and remember server address
  server.sin_addr.s_addr = inet_addr("127.0.0.1");
  // set the end point of transport
  if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {
    perror("socket call failed");
    exit(1);
  }
  // connect socket with server address
  if ( connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    perror("connect call failed");
    exit(1);
  }
 
  msgbody tmp;
  /*
   *  Recieve data from server
   */
  tmp.code = -1; // -1 = get list
  send(sockfd, &tmp, sizeof(msgbody), 0);
  while( ( recv(sockfd, &tmp, sizeof(msgbody), 0) > 0 ) && tmp.code == 1 ) {
    if(tmp.code == -2) break;
    printf("Code: %d\n", tmp.code);
    printf("Got Message\n");
    printf("%s: %s\n", tmp.name, tmp.msg);
    tmp.code = 0;
    push(root, &top, tmp);
  }
  printf("Reciving loop is not infinite!\n");
 
  /*
   *  Run client information sending.
   */ 
  time_t currenttime;
  char msgbuf[MSGSIZE];
  const char* name = "Author";
  while(1) {
    printf("Stared infinite loop\n");
    currenttime = time(NULL);
    // send information to server
    printf("Message: ");
    fgets(msgbuf, MSGSIZE - 1, stdin);
    strcpy(tmp.msg, msgbuf);
    strcpy(tmp.name, name);
    tmp.time = currenttime;
    // code 1 - normal message
    tmp.code = 1;
    send(sockfd, &tmp, sizeof(msgbody), 0);
  }
}

serwer

#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#include<time.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include "msgcontainer.h"
#include "config.h"
 
void usage(const char* argv1) {
  fprintf(stderr, "Need to create config file in user home directory: ~/.chatsrv/svr.conf\n");
  fprintf(stderr, "Check ~/.chatsvr/svr.conf.default\n");
  fprintf(stderr, "It is not a good idea to run this deamon as root!\n");
  fprintf(stderr, "Run '%s -D' to daemonize!\n", argv1);
  exit(0);
}
 
int main(int argc, char** argv)
{
 
  if ( ( argc == 2 && ( strcmp(argv[1], "--help") == 0 ) ) || argc > 2 )
    usage(argv[0]);
 
  /*
   *  Run in background
   */
  if(argc > 1 && ( strcmp(argv[1], "-D") == 0 ) ) {
    printf("Going background..\n");
    pid_t pid;
    switch( pid = fork() ) {
      case 0: // child
    break;
      default: // parent
    printf("Background %d\n", pid);
    return 0;
    }
  }
  /*
   *  Config loading.
   */
  init_directory();
  load_config();
 
  /*
   *  Container setup
   */ 
  msgroot* root = NULL;
  msglist* top = NULL;
  initialize_list(&root, &top);
  // push test messages
  msgbody tmp;
  strcpy(tmp.name, "Testowy autor");
  strcpy(tmp.msg, "Testowa wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);  
  strcpy(tmp.name, "autor");
  strcpy(tmp.msg, "wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);
  strcpy(tmp.name, "kolejny");
  strcpy(tmp.msg, "wiadomosc");
  tmp.time = time(NULL);
  push(root, &top, tmp);
  /*
   *  Run server
   */
  int sockfd, newsockfd;
  struct sockaddr_in server = {AF_INET, serverport, INADDR_ANY};
  // set the end point of the transport
  if( ( sockfd = socket(AF_INET, SOCK_STREAM, 0 )) == -1 ) {
    fprintf(stderr, "Socket call failed!\n");
    exit(1);
  }
  // bind server address with the end point
  if( bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) == -1 ) {
    fprintf(stderr, "Bind call failed!\n");
    exit(1);
  }
  // listen
  if( listen(sockfd, 5) == -1 ) {
    fprintf(stderr, "Listen call failed!\n");
    exit(1);
  }
 
  struct sockaddr_in client;
  int len = sizeof(struct sockaddr_in);
  char buff[MAX_LINE];
  // proceed connection
  printf("Started accept loop..\n");
  while(1) {
    // accept for connections
    if( ( newsockfd = accept(sockfd, (struct sockaddr*) &client, &len)) == -1 ) {
      fprintf(stderr, "Accept call failed!\n");
      continue;
    }
 
    // log connection
    FILE* fp;
    if( (fp = fopen(logpath, "a+")) == NULL  ) {
      fprintf(stderr, "Cannot open log file!\n");
      exit(1);
    }
    printf("Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fprintf(fp, "Connection from %s port %d\n", inet_ntop(AF_INET, &client.sin_addr, buff, 
                             sizeof(buff)), ntohs(client.sin_port));
    fclose(fp);
 
    // create child to proceed new connection
    if( fork() == 0 ) {
      // recieve data
      while( recv(newsockfd, &tmp, sizeof(msgbody), 0) > 0 ) {
    printf("Code: %d\n", tmp.code);
    /*
     * for code = -1 then send list of messages to the client
     */
    if(tmp.code == -1) {
      // display messages in the list
      if(root->first != NULL) {
        msglist* ptr = root->first;
        while(ptr != NULL) {
          printf("Sending..\n");
          printf("%s: %s\n", ptr->body.name, ptr->body.msg);
          // set flag for normal message
          ptr->body.code = 1;
          send(newsockfd, &(ptr->body), sizeof(msgbody), 0);
          // restore oryginal flag
          ptr->body.code = 0;
          ptr = ptr->next;
        }
        // send end transmission message code = -2
        tmp.code = -2;
        send(newsockfd, &tmp, sizeof(msgbody), 0);
      }
    }
 
    if(tmp.code == 1) {
      // push message to container
      // while push set code = 0
      tmp.code = 0;
      push(root, &top, tmp);
      printf("Number of elements: %d\n", size(root));
      printf(ctime(&tmp.time));
      printf("%s: %s", tmp.name, tmp.msg);
    }
      }
    }
  }
 
  return 0;
}

Czy jest to w miarę eleganckie, czy raczej nie o to chodziło. Jeżeli ktoś widzi jakieś mocno rzucające się w oczy błędy to będę wdzięczny za zwrócenie uwagi.

OK, ale zerknę jutro (dzisiaj), bo szczerze mówiąc już padam na pysk :) - Kumashiro 2011-08-24 01:57

Pozostało 580 znaków

2011-08-24 09:20
0

Jeśli chodzi o to blokowanie się na recv to może zainteresuj się funkcją select() zamiast kombinować z przesyłaniem dodatkowych danych? ;)

Pozostało 580 znaków

2011-08-25 11:50
Kumashiro
0
Newb napisał(a)

Jeżeli dobrze zrozumiałem, to obsługując gniazda domyślnie, czyli blokująco, pętla nigdy nie zakończy się. Czyli mój protokół jest odpowiedzialny za zakończenie pętli. Co innego w gniazdach nieblokujących, gdzie wszystko dzieje się asynchronicznie.

Inaczej, recv() blokuje, zatem każda iteracja pętli będzie wisiała na tym wywołaniu. Pętla zakończy się tylko wtedy, gdy recv() zwróci 0 lub błąd (-1). Dopóki serwer zgłasza, że jest gotowy nadawać, recv() blokuje.

Shalom udzielił Ci też dobrej rady - użyj select() lub *poll() do sprawdzania w jakim stanie aktualnie znajduje się kanał (czy druga strona chce nadawać, czy też może odbiera). Dodatkowo masz możliwość ustalenia timeoutów, czy robienia czegoś innego w międzyczasie.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0