Мне нужно написать программу для получения и обработки сообщения через сокет. У меня нет проблем, и я понимаю процесс создания сокета, привязки сокета, прослушивания входящего соединения и последующего его принятия. У меня проблемы с получением сообщения из файлового потока, который я создал для принятого соединения. Мой код приведен ниже (я включил почти все для справки, но я думаю, что проблема возникает после того, как соединение принято ..):
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(), но безрезультатно.
Я, вероятно, делаю глупую ошибку, но может ли кто-нибудь помочь мне с этим, пожалуйста?