繁体   English   中英

坚持标准输入阅读直到 ^C 或 EOF,然后“标准输入垃圾邮件”

[英]Stuck on stdin reading until ^C or EOF, then "stdin spam"

向任何有能力的人问好,他们会偶然发现我的帖子。
我需要前所未有的帮助。

我的问题在这里:

for(i = 1; i < 6; i++){
    wprintw(filsWin, "Entre ton choix en position %d :\n", i);
    wrefresh(filsWin);
                
    clean_stdin();
    choix = getchar();
                
    if(choix < '0' | choix > '7'){
        wprintw(filsWin, "Ce n'est pas dans les choix. Réessaie.\n");
        wrefresh(filsWin);
        i--;
    }
    else {
        combiGagnante[i-1] = choix;
        if(send(SockService, &choix, 1, 0) >= 0){
            wprintw(filsWin, "\n%s%cm%s%s inséré en position %d.\n\n", EXMNRM, combiGagnante[i-1], DOT, RSTCOL, i);
            wrefresh(filsWin);
        }
        else {
            perror("send()");
            raise(SIGINT);
        }
    }
}

我目前正在为我的学士学位制作 C 语言的策划者,它必须是 2 个 TCP 服务器 - 客户端程序。 由于其图形可能性,我想使用 ncurses 库,并且此代码是服务器的一部分,在连接客户端时由子进程执行。

问题出在choix = getchar(); .

无论这里使用什么来读取stdin ,我都可以输入任何内容,终端甚至不会回显它。 服务器上的^C幸运地退出了它(感谢我的信号捕获 tbh)。 但是,如果我在连接期间在客户端上^C ,客户端确实会像服务器一样终止(信号捕获 ftw),但是getchar()实际上无尽的 EOF (-1) 字符淹没(此代码以if (choix < '0' | choix > '7')语句),让我别无选择,只能最终^C服务器。

我已经江郎才尽,以解决这个问题,因为我不知道有什么可以可能的垃圾邮件stdin这样的。 我什至试图冲洗它并“清洁”它; 徒劳(我需要摆脱clean_stdin() ,它绝对没有任何作用)。

我对任何解决方案持开放态度,如果需要,可以提供更多信息和代码。

提前致谢!

Stack Overflow 新手

PS: choixint ,而不是char (为了方便起见), filsWin是孩子的subwin

编辑:响应@Armali,这里是server.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <uchar.h>

#include <arpa/inet.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>

#include <curses.h>

#include "mast_vars.h"

#define TRUE 1
#define FALSE 0

#define EXMNRM "\x1B[0;3"
#define RSTCOL "\x1B[0;0m"
//#define BLKCOL "\x1B[0;30m"
//#define REDCOL "\x1B[0;31m"
//#define GRNCOL "\x1B[0;32m"
//#define YLWCOL "\x1B[0;33m"
//#define BLUCOL "\x1B[0;34m"
//#define MAGCOL "\x1B[0;35m"
//#define CYACOL "\x1B[0;36m"
//#define WHTCOL "\x1B[0;37m"
#define DOT "\u2b24"
#define INVDOT "\u2022"


int SockEcoute, SockService;
WINDOW *pereWin, *filsWin;

int creerSocket(int, int *, struct sockaddr_in *);

void clean_stdin();

char convertPionIntoColor(char);

void segVSig(int sig);
void intSig(int sig);
void pipeSig(int sig);
void closeEverything();

int main(int argc, char *argv[]){
    struct sockaddr_in adresse;
    int portTCP, lg;
    
    char combiEssayees[5][essaisDonnes];
    char pionsInvest[5][essaisDonnes];
    
    int i, codGagne = 2, SockService = atoi(argv[1]);
    int32_t it;
    
    
    if(argc != 2 || argc == 1){
        fprintf(stderr, "Usage : MMSrvTCP <n°port>");
        exit(2);
    }

    signal(SIGINT, intSig);
    signal(SIGSEGV, segVSig);
    signal(SIGPIPE, pipeSig);
    
    portTCP=atoi(argv[1]);
    
    lg=sizeof(adresse);
    
    if((SockEcoute=creerSocket(SOCK_STREAM, &portTCP, &adresse))==-1){
        perror("Erreur creerSocket");
        exit(1);
    }
    
    if(listen(SockEcoute, 5)==-1){
        perror("Erreur listen");
        exit(2);
    }
    
    initscr();
    refresh();
    pereWin = subwin(stdscr, LINES / 2, COLS, 0, 0);
    box(pereWin, 0, 0);
    wrefresh(pereWin);
    
    wprintw(pereWin, "Serveur de PID %d lancé\n", getpid());
    
    while(1){
        wprintw(pereWin, "En attente d'un client.\n\n");
        wrefresh(pereWin);
        
        SockService=accept(SockEcoute, &adresse, &lg);
        wprintw(pereWin, "Connexion acceptée par %s\n", inet_ntoa(adresse.sin_addr));
        wrefresh(pereWin);
        
        if(fork() == 0){
            close(SockEcoute);
            dup2(SockService, STDIN_FILENO);
            close(SockService);
            
            filsWin = subwin(stdscr, LINES / 2, COLS, LINES / 2, 0);
            box(filsWin, 0, 0);
            wrefresh(filsWin);
            
            wprintw(filsWin, "Le choix de couleurs se fait ainsi :\n\n");
            wprintw(filsWin, "0 = Noir\n1 = Rouge\n2 = Vert\n3 = Jaune\n4 = Bleu\n5 = Magenta\n6 = Cyan\n7 = Blanc\n\n");
            wrefresh(filsWin);
            
            for(i = 1; i < 6; i++){
                wprintw(filsWin, "Entre ton choix en position %d :\n", i);
                wrefresh(filsWin);
                
                choix = getch();
                
                if(choix < '0' | choix > '7'){
                    wprintw(filsWin, "Ce n'est pas dans les choix. Réessaie.\n");
                    wrefresh(filsWin);
                    i--;
                }
                else {
                    combiGagnante[i-1] = choix;
                    if(send(SockService, &choix, 1, 0) >= 0){
                        wprintw(filsWin, "\n%s%cm%s%s inséré en position %d.\n\n", EXMNRM, combiGagnante[i-1], DOT, RSTCOL, i);
                        wrefresh(filsWin);
                    }
                    else {
                        perror("send()");
                        raise(SIGINT);
                    }
                }
            }
            
            do {
                wprintw(filsWin, "Combien veux-tu donner d'essais à ton décodeur ? 12 maxi.\n> ");
                wrefresh(filsWin);
                scanf("%d", &essaisDonnes);
                if(essaisDonnes > 12){
                    wprintw(filsWin, "C'est trop. Réessaie.\n");
                    wrefresh(filsWin);
                    //continue;
                }
                else if(essaisDonnes < 1){
                    wprintw(filsWin, "Bien tenté, mais tu ne peux pas ne pas lui donner d'essais. Réessaie.\n\n");
                    wrefresh(filsWin);
                    //continue;
                }
            } while(essaisDonnes >= 1 | essaisDonnes <= 12);
            
            it = htonl(essaisDonnes);
            if(send(SockService, &it, sizeof(it), 0) < 0){
                perror("recv() ");
                raise(SIGINT);
            }
            
            wprintw(filsWin, "Le décodeur se prépare...\n");
            wrefresh(filsWin);
            if(recv(SockService, &pret, 1, 0) < 0){
                perror("recv() ");
                raise(SIGINT);
            }
            
            if(pret == 'y' | pret == 'Y'){
                wprintw(filsWin, "Le décodeur est prêt, c'est parti.\n");
                wrefresh(filsWin);
                wgetch(filsWin);
            }
            else if(pret == 'n' | pret == 'N' | pret == 0x01){ // TODO : trouver le code FIN
                wprintw(filsWin, "Ah non, il est parti.\n\n");
                wrefresh(filsWin);
                close(SockService);
                wgetch(filsWin);
                wrefresh(filsWin);
                delwin(filsWin);
                clear();
                endwin();
                exit(1);
            }
            
            essaiActuel = 1;
            
            wclear(filsWin);
            
            while(essaiActuel <= essaisDonnes){
                wprintw(filsWin, "Essai N.%d en cours...\n\n", essaiActuel);
                wrefresh(filsWin);
                
                for(i = 0; i < 5; i++){
                    if(recv(SockService, &combiEssayees[i][essaiActuel-1], 1, 0) < 0){
                        perror("recv() ");
                        raise(SIGINT);
                    }
                    if(combiEssayees[i][essaiActuel-1] == 0x01){ // TODO : trouver le code FIN
                        wprintw(filsWin, "Le client nous a quitté.");
                        wrefresh(filsWin);
                        close(SockService);
                        wgetch(filsWin);
                        wrefresh(filsWin);
                        delwin(filsWin);
                        clear();
                        endwin();
                        exit(1);
                    }
                    
                    wprintw(filsWin, "%s%cm%s%s ", EXMNRM, combiEssayees[i][essaiActuel-1], DOT, RSTCOL);
                    //printw("%d octets reçus\n", nb);
                    wrefresh(filsWin);
                }
                
                wprintw(filsWin, "\n\nLe placement des pions d'investigation se fait ainsi :\n");
                wprintw(filsWin, "0 = Rien (mauvaise couleur, mauvais endroit)\n1 = Blanc (bonne couleur, mauvais endroit)\n2 = Noir (bonne couleur, bon endroit)\n\n");
                wprintw(filsWin, "C'est toi qui les place. Tu n'es pas obligé de les placer selon les positions.\n");
                wrefresh(filsWin);
                
                for(i = 0; i < 5; i++){
                    choix = wgetch(filsWin);
                    if(choix >= '0' | choix <= '2'){
                        pionsInvest[i][essaiActuel-1] = choix;
                        if(send(SockService, &choix, 1, 0) < 0){
                            perror("send()");
                            raise(SIGINT);
                        }
                        else {
                            wprintw(filsWin, "%s%cm%s%s ", EXMNRM, convertPionIntoColor(pionsInvest[i][essaiActuel-1]), INVDOT, RSTCOL);
                            wrefresh(filsWin);
                            
                            if(pionsInvest[i][essaiActuel-1] == '2') cpt++;
                        }
                    }
                    else {
                        wprintw(filsWin, "Ce n'est pas dans les choix. Réessaie.");
                        wrefresh(filsWin);
                        i--;
                    }
                }
                
                if(cpt == 5) {
                    codGagne = FALSE;
                    break;
                }
                else {
                    essaiActuel++;
                    if(essaiActuel > essaisDonnes) {
                        codGagne = TRUE;
                        break;
                    }
                    wprintw(filsWin, "Il a pas encore trouvé.");
                    wrefresh(filsWin);
                    wgetch(filsWin);
                }
            }
            
            switch(codGagne){
                case TRUE:
                    wprintw(filsWin, "C'est gagné ! Il a utilisé tous ses essais.");
                    wrefresh(filsWin);
                    break;
                case FALSE:
                    wprintw(filsWin, "Il a réussi en %d essais, dommage.", essaiActuel);
                    wrefresh(filsWin);
                    break;
                default:
                    wprintw(filsWin, "Ah ben le client est parti.\n");
                    wrefresh(filsWin);
                    break;
            }
            
            wprintw(filsWin, "Appuie sur n'importe quelle touche pour quitter.\n");
            wrefresh(filsWin);
            wgetch(filsWin);
            wrefresh(filsWin);
            delwin(filsWin);
            clear();
            endwin();
            exit(0);
        }
        
        wait(NULL);
        printf("oui");
        close(SockService);     
    }
}

int creerSocket(int type, int *portTCP, struct sockaddr_in *ptr_adresse){
    int desc;
    int longueur = sizeof(struct sockaddr_in);
    
    desc = socket(AF_INET, type, 0);
    if(desc==-1){
        perror("Erreur création de socket");
        return(-1);
    }
    
    ptr_adresse->sin_family = AF_INET;
    ptr_adresse->sin_port = htons(*portTCP);
    ptr_adresse->sin_addr.s_addr = INADDR_ANY;
    if((bind(desc, (struct sockaddr *)ptr_adresse, longueur))==-1){
        perror("Erreur bind");
        close(desc);
        exit(-1);
    }
    
    if(ptr_adresse != NULL)
        getsockname(desc, ptr_adresse, &longueur);
    
    return desc;
}



char convertPionIntoColor(char p){
    switch(p){
        case '0':
            return '\0';
        case '1':
            return '7';
        case '2':
            return '0';
        default:
            return -1;
    }
}


void segVSig(int sig){
    printf("Erreur de segmentation.\n");
    closeEverything();
}

void intSig(int sig){
    printf("Commande d'interruption reçue.\n");
    closeEverything();
}

void pipeSig(int sig){
    printf("\nSIGPIPE reçu : communication interrompue.\n");
    closeEverything();
}

void closeEverything(){
    printf("Fermeture forcée du serveur.\n\n");
    close(SockService);
    close(SockEcoute);
    delwin(filsWin);
    refresh();
    delwin(pereWin);
    refresh();
    clear();
    endwin();
    exit(1);
}

如果需要,我也可以发布客户。

编辑 2: mast_vars.h :

#ifndef _MAST_VARS_H
#define _MAST_VARS_H 1

int essaisDonnes, essaiActuel, choix;
int cpt = 0;

char pret;
char combiGagnante[5];

#endif

编辑 3:不再有essaisDonnes = 0; ,我将getchar()更改为getch()

我只是自己想出来的:

dup2()在 STDIN_FILENO 中创建连接文件描述符的副本,在close()之后仅在 stdin 中打开它,因此使用getchgetchar或任何其他函数读取 stdin 基本上是在等待客户端发送一些东西

删除两者都解决了我的问题: getch()现在可以正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM