2013-12-04 2 views
0

Я довольно новым для программирования сокетов, и у меня возникают проблемы отладки следующего кода:Странная перекручивание с сокетами

Клиент:

#define SIZE sizeof(struct sockaddr_in) 

int main(int argc, char* argv[]) { 
    printf("Starting setup\n"); 
    int sockfd; 
    int adder; 
    int sum; 
    struct sockaddr_in server; 
    server.sin_family = AF_INET; 
    server.sin_port = htons(7013); 
    inet_pton(AF_INET, "127.0.0.1", &server.sin_addr.s_addr); 

    printf("Setup complete\n"); 

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
     perror("Socket call failed.\n"); 
     return EXIT_FAILURE; 
    } 
    else{ 
     printf("socket: %i", sockfd); 
    } 

    //connect the socket 
    if (connect(sockfd, (struct sockaddr*) &server, SIZE) == -1) { 
     perror("Connect call failed"); 
     return EXIT_FAILURE; 
    } 

    //Send and receive 
    while (!feof(stdin)) { 
     printf("Input an integer \n"); 
     adder = atoi(fgets(intChar, 11, stdin)); 
     if ((send(sockfd, &adder, 11, 0)) == -1) { 
      perror("Send error"); 
     } 
     if (recv(sockfd, &sum, 1, 0) > 0) { 
      printf("%d", sum); 
     } 
     else { 
      printf("Server has died \n"); 
      close(sockfd); 
      return EXIT_FAILURE; 
     } 
    } 
    return EXIT_SUCCESS; 
} 

Сервер:

int sum = 0; 
int numconnections = 0; 

int main(int argc, char* argv[]) { 
    int sockfd; 
    int newsockfd; 
    int adder = 0; 
    struct sockaddr_in server; 
    server.sin_family = AF_INET; 
    server.sin_port = htons(7013); 
    server.sin_addr.s_addr = INADDR_ANY; 

    printf("Starting up. \n"); 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    //Free port 
    int on = 1; 
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 
    if (sockfd == -1) { 
     perror("Socket call failed. \n"); 
     return EXIT_FAILURE; 
    } 

    //bind address 
    if (bind(sockfd, (struct sockaddr*) &server, sizeof(server)) == -1) { 
     perror("Bind call failed. \n"); 
     return EXIT_FAILURE; 
    } 

    //listen 
    if (listen(sockfd, 5) == -1) { 
     perror("Listen call failed. \n"); 
     return EXIT_FAILURE; 
    } 
    while (numconnections < 2) { 
     //accept a connection 
     printf("ready to accept connections\n"); 
     if ((newsockfd = accept(sockfd, NULL, NULL)) == -1) { 
      perror("Accept call failed. \n"); 
      continue; 
     } 
     printf("New connection detected"); 
     numconnections++; 
     //spawn child to deal with it 
     if (fork() == 0) { 
      while (recv(newsockfd, &adder, 1, 0) > 0) { 
       printf("Sum is %d \n", sum); 
       printf("Adder is %d \n", adder); 
       sum += adder; 
       printf("Sending sum %d \n", sum); 
       send(newsockfd, &sum, 1, 0); 
      } 
      close(newsockfd); 
      return EXIT_SUCCESS; 
     } 
    } 
    close(newsockfd); 
     close(sockfd); 

    return EXIT_SUCCESS; 
} 

Независимо о том, запускаю ли я программы на одном компьютере или отдельно, когда сервер получает сокет, он продолжает добавлять числа примерно 10 раз подряд, почти так же, как если сокет зацикливается.

Вот некоторый пример вывод после того, как я представляю 3 от клиента:

Starting up. 
ready to accept connections 
New connection detectedready to accept connections 
New connection detectedSum is 0 
Adder is 3 
Sending sum 3 
Sum is 3 
Adder is 0 
Sending sum 3 
Sum is 3 
Adder is 0 
Sending sum 3 
Sum is 3 
Adder is 0 
Sending sum 3 
Sum is 3 
Adder is 77 
Sending sum 80 
Sum is 80 
Adder is 11 
Sending sum 91 
Sum is 91 
Adder is 64 
Sending sum 155 
Sum is 155 
Adder is 0 
Sending sum 155 
Sum is 155 
Adder is 3 
Sending sum 158 
Sum is 158 
Adder is 0 
Sending sum 158 
Sum is 158 
Adder is 0 
Sending sum 158 

На стороне клиента, я получаю обратно-сначала, но потом я получаю некоторый нонсенс номер как 4197123.

У меня есть сильное чувство, что я упускаю что-то очевидное. Заранее спасибо.

+2

'while (recv (newsockfd, & adder, 1, 0)> 0) {' Использовать возвращаемое значение из recv() является последним фактически полученным байтом. Третий аргумент также неверен. – wildplasser

+0

О, я вижу, третий аргумент для размера буфера, поэтому я должен использовать sizeof (int). –

+0

По крайней мере. Или буфер между вызовами, что необходимо, поскольку TCP не имеет границ сообщений: поток может быть разбит в любой точке. – wildplasser

ответ

2
while (recv(newsockfd, &adder, 1, 0) > 0) { ... 

использовать возвращаемое значение из recv() Это количество фактически полученных байтов. Третий аргумент также неверен. Он должен по крайней мере sizeof (int). Или вы можете буферизовать частичные приемы между вызовами, что необходимо, поскольку TCP не имеет границ сообщений: поток можно разбить в любой момент. (см. мой эскиз для буферизации here)

Вы также должны изменить третий аргумент для send(); send() похоже.

adder = atoi(fgets(intChar, 11, stdin)); 
if ((send(sockfd, &adder, 11, 0)) == -1) { ... 

(клиент) также очень не прав, вы отправляете int, а не строку.

И наконец: не используйте feof(), по крайней мере, не таким образом. feof() вернет ненулевое значение после Ошибка fgets() завершилась неудачно, аргумент NULL, вероятно, будет allready havecrash atoi().

+0

Я удалил клиентский цикл, в любом случае это было лишним. –

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