I am trying to write a simple chat application using TCP protocol in Linux, in which server receives strings from the client and it sends strings size to the client. When I run client, the server throws a “Bad file descriptor” error and exits. Nevertheless if I send input strings by client it receives correct sizes of strings, but as I said before server goes down. Here is the code :
SERVER
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #define MAX_LINE 1024 int main(int argc, char const *argv[]) { int listen_fd, connect_fd, logging, str_lenght; struct sockaddr_in serv_addr, client; char buffer_str[MAX_LINE], buffer[MAX_LINE]; pid_t pid; socklen_t len; logging = 1; if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(1024); if (bind(listen_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("bind"); exit(-1); } if (listen(listen_fd, 1024) < 0) { perror("listen"); exit(-1); } for (;;) { len = sizeof(client); if ((connect_fd = accept(listen_fd, (struct sockaddr *)&client, &len)) < 0) { perror("accept"); exit(-1); } if ((pid = fork()) < 0) { perror("fork"); exit(-1); } if (pid == 0) { close(listen_fd); for (;;) { bzero(buffer_str, MAX_LINE); if (read(connect_fd, buffer_str, sizeof(buffer_str)) < 0) { perror("read"); exit(-1); } if (strcmp(buffer_str, "exit") == 0) break; str_lenght = (int)strlen(buffer_str) - 1; bzero(buffer_str, MAX_LINE); snprintf(buffer_str, sizeof(buffer_str), "%dn", str_lenght); if (write(connect_fd, buffer_str, sizeof(buffer_str)) < 0) { perror("write"); exit(-1); } if (logging) { inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer)); printf("Request from host %s, port %dn", buffer, ntohs(client.sin_port)); } } close(connect_fd); exit(0); } else close(listen_fd); } exit(0); }
CLIENT
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #define MAX_LINE 1024 void clientEcho(int socket_fd) { char recv_buffer[MAX_LINE], send_buffer[MAX_LINE]; for (;;) { bzero(recv_buffer, MAX_LINE); bzero(send_buffer, MAX_LINE); printf("insert string: "); if (fgets(send_buffer, sizeof(send_buffer), stdin) == NULL) { perror("fgets"); return; } if (write(socket_fd, send_buffer, sizeof(send_buffer)) < 0) { perror("write"); return; } if (strcmp(send_buffer, "exit") == 0) break; if (read(socket_fd, recv_buffer, sizeof(recv_buffer)) < 0) { perror("read"); return; } printf("string size: "); if (fputs(recv_buffer, stdout) < 0) { perror("fputs"); return; } } } int main(int argc, char const *argv[]) { int socket_fd; struct sockaddr_in serv_addr; if (argc != 2) { perror("usage: <IPaddress>"); exit(-1); } if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(-1); } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(1024); if (inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) { perror("inet_pton"); exit(-1); } if (connect(socket_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { perror("connect"); exit(-1); } clientEcho(socket_fd); close(socket_fd); exit(0); }
Advertisement
Answer
In addition to what the other answer says: you’re never sending the "exit"
string, but "exitn"
(i.e. followed by a newfile — and 1019 zero bytes), and the strcmp(buffer_str, "exit") == 0
in the server will never be true.
BTW, this piece is code is broken:
bzero(buffer_str, MAX_LINE); if (read(connect_fd, buffer_str, sizeof(buffer_str)) < 0) { perror("read"); exit(-1); } if (strcmp(buffer_str, "exit") == 0) break; str_lenght = (int)strlen(buffer_str) - 1;
If the read
returns exactly sizeof(buffer_str)
bytes, the buffer may not be zero-terminated, and you could not use strcmp
on it. And I don’t see the point of setting str_lenght
(sic) to one less than the actual length of the string.