Попытка принять сокетное соединение, получить и обработать сообщение, а затем записать это сообщение в терминал

Мне нужно написать программу для получения и обработки сообщения через сокет. У меня нет проблем, и я понимаю процесс создания сокета, привязки сокета, прослушивания входящего соединения и последующего его принятия. У меня проблемы с получением сообщения из файлового потока, который я создал для принятого соединения. Мой код приведен ниже (я включил почти все для справки, но я думаю, что проблема возникает после того, как соединение принято ..):

int sockfd; // the socket file descriptor
int conn_fd; // the accepted connection file descriptor
FILE *conn_fs; // the file stream for the accepted connection
char *conn_buff;
//char conn_buff[LINE_MAX]; // a buffer to store the data received from the accepted connection

int main(int argc, char *argv[]) {
int port = 0;
if ((argc != 2) || (sscanf(argv[1], "%d", &port) != 1)) {
    fprintf(stderr, "Usage: %s [PORT]\n", argv[0]);
    exit(1);
}

if (port < 1024) {
    fprintf(stderr, "Port must be greater than 1024\n");
    exit(1);
}

struct sockaddr_in servaddr; // socket address structure (socket in address)
// set all bytes in socket address structure to zero, and fill in the relevant data members
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port); // port is the first argument given in the terminal

// tell the user the servaddr structure has been initialised.
//printf("servaddr structure has been initialised..\n\ncreating socket..\n");

// create the socket using IPv4 (AF_INET) and 2-way comms (SOCK_STREAM)
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { // socket() returns < 0 if an error occurs
    printf("error: creating the socket..\nexitting..\n");
    exit(EXIT_FAILURE);
}

// tell the user the socket has been created
//printf("socket created..\n\nbinding socket..\n"); 

// bind the socket to the socket address structure defined above
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) { // bind() returns < 0 if an error occurs
    printf("error: binding the socket..\nexitting..\n");
    exit(EXIT_FAILURE);
}

// tell the user the socket is "bound"
//printf("socket is now \"bound\"..\n\nmarking the socket as passive..\n");

// set the socket to accept incoming connections (listen)
if (listen(sockfd, SOMAXCONN) < 0) { // listen() returns < 0 if an error occurs
    printf("error: marking the socket as a passive socket in the function listen()..\nexitting..\n");
    exit(EXIT_FAILURE);
}

// tell the user the socket is listening for incoming connections
printf("socket is now passive (listening)..\n\naccepting incoming connections..\n");

// accept an incoming connection
if (conn_fd = accept(sockfd, NULL, NULL) < 0) { // accept() returns < 0 if an error occurs
    printf("error: accepting an incoming connection..\nexitting..\n");
    exit(EXIT_FAILURE);
}

// tell the user a connection has been accepted
printf("a connection has been accepted..\n\ncreating a file stream for this connection..\n");
    /*
// open a file stream associated with conn_fd
if ((conn_fs = fdopen(conn_fd, "r+")) == NULL) { // fdopen() returns NULL if an error occurs
    printf("error: associating a stream to the connections file descriptor in the function fdopen()..\nexitting..\n");
    exit(EXIT_FAILURE);
}

    // echo out the incoming message
    /*while (fgets(conn_buff, LINE_MAX, conn_fd) != NULL) { // fill the conn_buff buffer with data from the file stream conn_fs. returns NULL on error or EOF
    //while (read(conn_fd,conn_buff,sizeof(char)*LINE_MAX) > 0) {
        printf(conn_buff);printf("OH HAIIIIIIIIIIIIIIIIIIIIIIIIII\n");
    } printf("OH HAI\n");*/        

    size_t len = 100;
    ssize_t read;
    while ((read = getline(&conn_buff, &len, conn_fs)) != -1) {
        printf("Retrieved line of length %zu :\n", read);
        printf("%s", conn_buff);
    }

    free(conn_buff);

    // check if there was an error
    if (ferror(conn_fs) != 0) { // returns nonzero if the error indicator is set for conn_fs (eg, if fgets() above returned NULL due to an error)
        printf("error: an error occurred whilst retrieving data from the stream..\nexitting..\n");
        exit(EXIT_FAILURE);
    }

// close the file stream associated with conn_fd
if (close((int) conn_fs) != 0) { // close the file stream
    printf("error: closing the file stream..\nexitting..\n");
    exit(EXIT_FAILURE);
}


exit(EXIT_SUCCESS);
}

Когда я запускаю программу, она останавливается внутри цикла while ((read = getline(.... Если я нажму Enter, чтобы очистить буфер, я получу «Восстановленную строку длины 1:» с терминала. Я понял, что программа (почему-то я не могу понять) читает со стандартного ввода. Он ждет, пока я что-нибудь наберу, и как только я очищаю буфер (т.е. нажимаю Enter), он отправляет все обратно мне. Единственный способ закрыть программу — использовать Ctrl+C. По этой причине я думаю, что есть проблема с моим утверждением if ((conn_fs = fdopen(conn_fd, "r+")) == NULL) {.

Я пробовал МНОГИЕ разные способы чтения из потока (fread(), read(), getline(), fgets(), fgetc()...), и все они имели одинаковый эффект. Затем, когда я понял, что проблема должна быть в том, как я открываю файловый поток, я попытался использовать fopen(), но безрезультатно.

Я, вероятно, делаю глупую ошибку, но может ли кто-нибудь помочь мне с этим, пожалуйста?


person Elliot    schedule 02.12.2012    source источник
comment
часть, где вы делаете if(conn_fs = fdopen(conn_fd,r+)).. кажется, закомментирована. Это ваш оригинальный код?   -  person Bug Killer    schedule 03.12.2012
comment
кстати, close((int) conn_fs) неверен. close принимает аргумент файлового дескриптора, а не FILE*.   -  person Bug Killer    schedule 03.12.2012


Ответы (1)


Клиент никогда не закрывает соединение.

person user207421    schedule 02.12.2012