[英]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: choix
是int
,而不是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 中打开它,因此使用getch
、 getchar
或任何其他函数读取 stdin 基本上是在等待客户端发送一些东西。
删除两者都解决了我的问题: getch()
现在可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.