Ошибка SIGPIPE в параллельном эхо-отчете на основе TCP - PullRequest
0 голосов
/ 04 февраля 2012

Я новичок в сетевом программировании и научился этому, написав небольшие программы, использующие Socket API.В настоящее время я пишу простой эхо-сервер, который использует fork для создания его копии, как только он получает запрос на подключение, это выглядит как улучшение по сравнению с предыдущим Итеративным сервером (здесь) .Однако после того, как я запустил сервер, запустил клиент и ввел сообщение на его консоли, он неожиданно завершил работу.Запуск программы под Gdb показывает, что SIGPIPE доставлено.Но насколько я знаю, поскольку сокет все еще действителен, SIGPIPE не должен был произойти.Любая вовлеченная помощь приветствуется.Вот код клиента

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>

#define MAXCOUNT 1024

int main(int argc, char* argv[])
{
    int sfd,i;
    struct sockaddr_in saddr;
    char buff[MAXCOUNT];
    char mesg[MAXCOUNT];
    sfd = socket(AF_INET,SOCK_STREAM,0);
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    inet_pton(AF_INET,"127.0.0.1",&saddr.sin_addr);
    saddr.sin_port = htons(5008);
    connect(sfd,(struct sockaddr*) &saddr,sizeof(saddr));
    fgets(buff,MAXCOUNT,stdin);
    send(sfd,buff,strlen(buff),0);
    if (recv(sfd,mesg,MAXCOUNT,0) == -1) {
        perror("Nothing to read\n");
        exit(1);
    }
    printf("%s\n",mesg);
    exit(0);    
}

Вот код сервера

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>

#define MAXCOUNT 1024

int main(int argc, char* argv[])
{
    int sfd,nsfd,cn;
    pid_t c;
    char buf[MAXCOUNT];
    socklen_t clen;
    struct sockaddr_in caddr,saddr;

    sfd = socket(AF_INET,SOCK_STREAM,0);
    memset(&saddr,0,sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    saddr.sin_port = htons(5008);

    bind(sfd,(struct sockaddr*) &saddr,0);

    listen(sfd,2);
    for (; ;) {
        clen = sizeof(caddr);
        nsfd = accept(sfd,(struct sockaddr*) &caddr, &clen);
        if( (c = fork()) == 0) {
            close(sfd);
            memset(buf,0,sizeof(buf));
            cn = recv(nsfd,buf,sizeof(buf),0);
            if ( cn == 0) {
                perror("Reading from the client socket failed\n PROGRAM CRASH :\n");
                exit(1);
            }
            buf[cn] = '\0';
            send(nsfd,buf,strlen(buf),0);
            close(nsfd);
            exit(0);
        }
    }
    return 0;
}

1 Ответ

0 голосов
/ 04 февраля 2012
send(sfd,buff,strlen(buff),0);
if (recv(sfd,mesg,MAXCOUNT,0) == -1) {
    perror("Nothing to read\n");
    exit(1);
}
printf("%s\n",mesg);

Спецификатор формата %s предназначен для строк в стиле C, а не для произвольных данных. А поскольку вы отбрасываете возвращаемое значение из recv, у вас нет возможности узнать, сколько байт вы получили.

Ваш клиент также не закрыл сокет изящно и не удостоверился, что он получил все данные, которые сервер может отправить. Так что возможно, что вы запускаете ненормальное завершение. Сервер закрывает соединение после завершения отправки, поэтому клиент должен продолжать пытаться получить, пока не обнаружит, что соединение закрыто.

...