Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ UNIX域套接字读取()总是获取错误的值_C++_Sockets - Fatal编程技术网

C++ UNIX域套接字读取()总是获取错误的值

C++ UNIX域套接字读取()总是获取错误的值,c++,sockets,C++,Sockets,我必须用UNIX域套接字作为赋值来编写一个游戏。服务器和客户端在同一台机器上,只是为了了解IPC 每艘船都有一号的 我遇到了一个我无法解决的问题,我希望你有一个想法 首先我知道read(),write(),select()。。。有一个返回值,我检查它们。但是我不想让他们知道代码可读性更好。我还省略了其他不必要的代码 除了连接(这不是问题)之外,服务器和客户端几乎相同,它们处于相反的状态,使用turn==0和turn=0我又写了一篇 所以我的问题是:在else中,由于if中的控制台输入,read函

我必须用UNIX域套接字作为赋值来编写一个游戏。服务器和客户端在同一台机器上,只是为了了解IPC

每艘船都有一号的

我遇到了一个我无法解决的问题,我希望你有一个想法

首先我知道read(),write(),select()。。。有一个返回值,我检查它们。但是我不想让他们知道代码可读性更好。我还省略了其他不必要的代码

除了连接(这不是问题)之外,服务器和客户端几乎相同,它们处于相反的状态,使用turn==0和turn=0我又写了一篇

所以我的问题是:在else中,由于if中的控制台输入,read函数是非阻塞的。我试图用select解决这个问题,但我总是得到错误的输入。在第一个移动中,它始终在中读取(0,0)。在敌方回合中,它使用上一次输入的数据。

int main(int argc, const char * argv[])
{
    if(argv[1]==NULL){
        std::cout << "no socket path" << std::endl;
        return 1;
    }

    Playfield field(5);

    fd_set rfds;
    FD_ZERO(&rfds);


    int turn = 0;
    int sock;
    struct sockaddr_un address;
    int cordinate[2];
    int status[1];
    int gameInfo[1];

    if((sock = socket(AF_UNIX, SOCK_STREAM,0)) < 0){
        std::cerr << "error creating socket" << std::endl;
    }

    address.sun_family = AF_UNIX;
    strcpy(address.sun_path, argv[1]);

    std::cout << "trying to connect..." << std::endl;

    if(connect(sock,(struct sockaddr*) &address, sizeof(address)) == 0){
        std::cout << "conected" << std::endl;

    int inputHeight;
    char inputLengthChar;
    bool noWinnerFound=true;
    FD_SET(sock, &rfds);

    while(noWinnerFound){

        read(sock, gameInfo, 1);
        if(gameInfo[0]<=0){
            std::cout << std::endl;
            std::cout << "you have won. congratulation!" << std::endl;
            noWinnerFound=false;
            break;
        }
        gameInfo[0] = field.getRemainingShips();
        write(sock, gameInfo, 1);

        if(field.getRemainingShips()<=0){
            std::cout << std::endl;
            std::cout << "you have lost." << std::endl;
            noWinnerFound=false;
            break;
        }

        if(turn%2!=0){
            std::cout << "your turn: " << std::endl;
            std::cout << std::endl;
            field.print();
            std::cout << "enter which field you want to attack" << std::endl;
            std::cin >> inputHeight >> inputLengthChar;
            if(inputHeight>field.getHeight() || inputHeight<0 ||((int)(inputLengthChar-65))>=field.getLength() || (int)inputLengthChar-65<0){
                std::cin.setstate(std::cin.failbit);
            }
            else if(field.getEnemyField(inputHeight-1,((int)(inputLengthChar-65))!=field.EMPTY_FIELD)){
                std::cout << "you already attacked that field" << std::endl;
                std::cin.setstate(std::cin.failbit);
            }
            while(std::cin.fail()){
                std::cout << "Please enter: number character" << std::endl;
                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
                std::cin >> inputHeight >> inputLengthChar;
                if(inputHeight>field.getHeight() || ((int)inputLengthChar)-65>=field.getLength()){
                    std::cin.setstate(std::cin.failbit);
                }
                else if(field.getEnemyField(inputHeight-1,((int)(inputLengthChar-65))!=field.EMPTY_FIELD)){
                    std::cout << "you already attacked that field" << std::endl;
                    std::cin.setstate(std::cin.failbit);
                }
            }

            cordinate[0] = inputHeight-1;
            cordinate[1] = ((int)(inputLengthChar-65));
            if(write(sock, cordinate, 2) == -1)
                std::cerr << "error writing" << std::endl;
            //select(sock2, &rfds, NULL, NULL, &stop);
            int n = select(sock+1, &rfds, NULL, NULL, NULL);
            if(n == -1){
                std::cerr << "error select" << std::endl;
            } else{
                if(FD_ISSET(sock, &rfds)){
                    if(read(sock, status, 1) == -1)
                        std::cerr << "error reading" << std::endl;
                    if(status[0]==field.SHIP){
                        field.setEnemyField(cordinate[0], cordinate[1], field.SHIP);
                        std::cout << std::endl;
                        std::cout << "you hit a ship" << std::endl;
                    }

                    else{
                        field.setEnemyField(cordinate[0], cordinate[1], field.ATTACKED);
                    }
                }
            }

            field.print();
            ++turn;

        }

        else{
            std::cout << std::endl;
            std::cout << "enemy turn please wait" << std::endl;
            int n = select(sock+1, &rfds, NULL, NULL, NULL);
            if(n == -1){
                std::cerr << "error select" << std::endl;
            } else{
                if(FD_ISSET(sock, &rfds)){
                    if(read(sock, cordinate, 2) <= 0)
                        std::cerr << "error reading" << std::endl;
                    status[0] = field.getField(cordinate[0], cordinate[1]);
                    write(sock, status, 1);
                    if(status[0]==field.SHIP){
                        field.decreaseRemainingShips();
                    }
                    else if(status[0]==field.EMPTY_FIELD){
                        field.setField(cordinate[0], cordinate[1], field.ATTACKED);
                    }
                }
            }
            ++turn;
        }
    }
}
else{
    std::cout << "no server found" << std::endl;
    exit(1);
}

close(sock);

return 0;
游戏开始时,您会看到一块白板,代表敌方棋盘和服务器攻击区域(1,B)。输出为:

   server:         client:
  A B C D E       A B C D E
1   X           1 
2               2   
3               3     
4               4       
5               5         
   server:         client:
  A B C D E       A B C D E
1   X           1 O
2               2   
3               3     
4               4       
5               5    
这显然是错误的,但它使用了敌方回合中字段(1,A)的值,它使用了服务器输入字段的值。假设客户端攻击(1,A)会击中船只,但由于上次攻击没有击中船只,因此输出为:

   server:         client:
  A B C D E       A B C D E
1   X           1 
2               2   
3               3     
4               4       
5               5         
   server:         client:
  A B C D E       A B C D E
1   X           1 O
2               2   
3               3     
4               4       
5               5    

我希望我能说清楚。如果有人能帮忙,我将不胜感激。

您使用的是一个部分未初始化的变量
gameInfo
是一个整数(通常为四个字节),但您只能读取其中的一个字节。此外,由于您实际上在其他地方将其用作int,因此endianness问题也起了作用


你在这里很幸运,因为你可能在一个小小的endian平台上,但是你仍然不能通过读取一个以前没有的值来使
gameInfo
为负值,反之亦然,如果它以前为负值则不能使其为正值。

你不能忽略读取的返回值。正确性取决于它。在问题行中,您忽略了它,这可能是您遇到的问题的一部分。如果它返回1,而您希望读取2个字节,该怎么办?谢谢您的回复。正如我在本主题开始时提到的,我检查它们,我只是把它们放在这里,因为这里可读性更好。在代码样本中存在明显的“错误”错误时,我很难找到真正的错误。请发布完整版本,在你看来,100%正确。许多人误用
阅读
(因为很难正确使用),我无法从这段代码中判断您的使用是否正确。在这种情况下,我怎么能发现你的问题呢?你甚至说问题就在这条线上!我如何查看您未显示的代码行?已更改。我没有出现是因为我认为这会让其他人更容易阅读。并认为这不是问题所在。我只是抄了我的客户。不管怎样,我感谢你的帮助,谢谢你抽出时间来阅读。既然你提到了这件事,它就像一辆卡车一样击中了我。我不知道为什么我把这个设置为只有1字节,看看其他的读写操作,我也犯了类似的错误。谢谢我纠正了所有这些故障,现在它可以正常工作了。谢谢你们两位的帮助。