没有数据发送时如何跳过recv()函数

时间:2019-12-13 16:40:47

标签: c sockets server parent-child recv

我有一个用C编写的服务器-客户端程序。我的问题是我有一个while循环,可以在其中接收和发送数据。当我需要服务器做其他事情时,它会发生很多,但是它只是停在recv()函数上,并等待来自客户端的数据。我该如何克服?我已经尝试过:

 int waitForAnswer =1;
 if((childpid = fork()) == 0){
     close(socketfd);
     close(fd[0]);

        while(1){
            if(waitForAnswer) {
                receive(newSocket, buff) == 0;
                parseRecvMess(buff);
             }
             waitForAnswer  =0;

但是它不起作用。由于某种原因,程序在接受带有“无套接字”错误的套接字时以退出代码1结尾。 这是我的程序;

nt main(){
    int size = 256;
    char buff[size];
    char sbuff[size];
    int n;
    int reader;
    int socketfd, ret;
    struct sockaddr_in serverAddr;
    int newSocket = -2;
    struct sockaddr_in newAddr;
    socklen_t addr_size;
    pid_t childpid;
    pocet_hracu = 0;

    srand(time(NULL));
    initializeLobby();
    memset(buff, 0, size);
    memset(sbuff, 0, size);

    socketfd = socket(AF_INET,SOCK_STREAM,0);


    if(socketfd < 0){
        printf("\n error in socket creation");
        return -1;
    }
    printf("\n Server socket is created\n");


    memset(&serverAddr, '\0', sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

    ret = bind(socketfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));

    if(ret < 0){
        printf("Error in binding\n");
        return -1;
    }
    printf("[*]Bind to port %d\n", PORT);

    if(listen(socketfd, 10) == 0){
        printf("Listening...\n");
    }else{
        printf("Error in binding\n");
    }

    // pipe pro komunikaci
    int readpipe;
    int writepipe;
    int fd[2];
    pipe(fd);

    for (;;) {
            newSocket = accept(socketfd, (struct sockaddr *) &newAddr, &addr_size);
            if (newSocket < 0) {
                printf("No socket\n");
                exit(1);
            }
//            struct timeval tv;
//            tv.tv_sec = 1;
//            tv.tv_usec = 0;
//            setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
            // read the message from client and copy it in buffer
            receive(newSocket, buff);
            parseRecvMess(buff);
            printf("\n%s sent: %s", user, command);

            if (strncmp(" new", command, 4) == 0) {
                player newPlayer;
                newPlayer.name = (char *) malloc(sizeof(char) * 10); // *login must contain up to 10 characters
                strcpy(newPlayer.name, user);
                newPlayer.gameScore = 0;
                newPlayer.roundScore = 0;
                newPlayer.socket = newSocket;
                // TODO vztvorit pipe pro kounikaci
                // newPlayer.readpipe
                // newPlayer.writepipe
                addToPlayersArray(&newPlayer); //TODO player index is not increasing
                addToLobby(&newPlayer);
                printf("Server : %s uspesne prihlasen.\n", newPlayer.name);
            }


            bzero(buff, size);
            printf("To client : OK\n");
            strcpy(sbuff, "OK\n" );
            sendMess(newSocket, sbuff, sizeof(sbuff));

            int waitForAnswer =1;
        if((childpid = fork()) == 0){
            close(socketfd);
            close(fd[0]);

            while(1){
                printf("MAIN->while(1)\n");
                // poslouchame zpravy
                //if(waitForAnswer) {
                receive(newSocket, buff) == 0;
                parseRecvMess(buff);
                //}
                waitForAnswer  =0;




                if(strcmp(buff,":exit") == 0){
                    printf("Disconnected from %s:%d\n", inet_ntoa(newAddr.sin_addr), ntohs(newAddr.sin_port));
                    break;
                } else{
                    // send buff to parent
                    int i = findPlayerIndex();
                    memset(sbuff, '\0', size)  ;
                    str str;
                    strcat(sbuff, "//:");
                    sprintf(str, "%d", i);
                    strcat(sbuff, str);
                    strcat(sbuff, ":");
                    strcat(sbuff, command);
                    strcat(sbuff, "\n");
                    write(fd[1], sbuff , strlen(sbuff)+1);
                    bzero(buff, sizeof(buff));



                    if (strncmp("roll", command, 4) == 0) {
                        //TODO

                        hod();
                    }
                    if (strncmp("none", command, 4) == 0) {
                        //TODO
                    }

                    strcpy(sbuff, "OK\n" );
                    write(newSocket, sbuff, strlen(sbuff));
                    bzero(buff, sizeof(buff));
                    bzero(sbuff, sizeof(sbuff));
                }
            }
        } 
            close(fd[1]);
            int nbytes = read(fd[0], buff, sizeof(buff));
            printf("PARENT: buffer : %s\n",buff);

            parseRecvMess(buff);

            char *index1= (char *)malloc(sizeof(char)*10);
            strcpy(index1, user);
            int index = atoi(index1);
            char *command1= (char *)malloc(sizeof(char)*10);
            strcpy(command1, command);
            //printf("PARENT - index:%d, command:%s\n", index, command );
            printf("PARENT - index:%d, jmeno:%s, command:%s\n", index, players_array[index].name, command1 );
            bzero(buff, sizeof(buff));


        if (strncmp("room", command1, 4) == 0) {
                        // vlozit do mistnosti
                        printf("command = room\n");
                        command = strtok(command1," ");
                        command = strtok(NULL," "); // volba
                        printf("command(volba): + %s \n", command);
                        //int i = findPlayerIndex(); // find player in array based on user name
                        printf("player index: = %d \n", index);
                        //printPlayer(&players_array[i]);
                        volbaHry(&players_array[index], command, lobby);
                        //players_array[i].mist->pocet_hracu++;
                        printf("PARENT: array pocet hracu %d\n",players_array[index].mist->pocet_hracu);
                        printf("PARENT: lobby pocet hracu %d\n",lobby[0].pocet_hracu);
                        str str;
                        memset(sbuff, '\0', size);

                        //pokud v mistnosti jsou 2 hraci => zacina hra
                        if( players_array[index].mist->pocet_hracu == 2){
                            printf("Hra zacina ...\n");
                            hra(players_array[index].mist);
                        }
                        printMistnost(players_array[index].mist);
                    }

            //players_array[index].mist = lobby[volba - 1];
//        }

    }
    close(newSocket);

    return 0;
}

这是我的receive()函数:

int receive(int socket, char *buff){
    int size = 256;
    int reader = recv(socket, buff, size * sizeof(char), 0);
    if (reader == -1) {
        printf("BREAK reader == -1\n");
        perror("recv()");
        return(-1);
    } else if (reader == 0) {
        printf("BREAK reader == 0\n");
        return(-2);
    } else if(checkMessage(buff) == 0){
        printf("ERROR: recieved message is not valid\n");
        return(-3);
    }
    return 0;
}

如果我不使用waitForAnswer变量,则程序将与客户端连接而没有任何错误,但有时在等待另一条消息时会在开始时停止。

2 个答案:

答案 0 :(得分:1)

使用无阻塞标志调用recv:

recv(socket, buff, size, MSG_DONTWAIT);

如果没有要读取的数据,该函数将立即返回。

答案 1 :(得分:1)

如果套接字设置为非阻塞,您还可以使用ioctl()检查数据

#include <sys/ioctl.h>


int status;

do{
    ioctl(socketfd, FIONREAD, &status);
    if( status > 0 ){
     //packet waiting to be read
     recv(socketfd, buff, size * sizeof(char), 0);
    }
    else{
      // no data .. so do something else
    }
  } while (!must_stop);