如果未添加睡眠,则C ++套接字不发送数据

时间:2015-02-11 11:57:25

标签: c++ sockets c++11 sleep

我正在用C ++为我的AI项目编写客户端,该项目与用Java编写的服务器通信,我无法访问该代码。他们使用TCP套接字进行通信:服务器向我发送消息,客户端相应地执行操作,例如生成移动或更新电路板或声明胜利,失败等。现在我注意到有时套接字卡住并且服务器发回超时消息,即使客户端从未生成移动并且从未输入" YOUR_MOVE"否则,如果,这很奇怪,因为它立即计算移动(少数几毫秒),如果我在发送或接收之前添加50毫秒的睡眠,它就像一个魅力。我想知道什么可能出错。那是代码:

    #include <iostream>
    #include <cstring>      // Needed for memset
    #include <sys/socket.h> // Needed for the socket functions
    #include <netdb.h>      // Needed for the socket functions
    #include <unistd.h>
    #include <string>
    #include <boost/algorithm/string/predicate.hpp>
    #include <boost/lexical_cast.hpp>
    #include <chrono>
    #include "AI.cpp"
    #include <locale>
    #include <thread>

    using namespace::std;

    void error(const char *msg)
    {
         perror(msg);
        exit(0);
    }

    class Client{

    private:
        AI* ai;
    public:
        int socketfd;

    Client(const char* serverAddress, const char* port){
        int status;


        struct sockaddr_in serv_addr;
        struct hostent *server;



        portno = 8901;

        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        if (sockfd < 0)
            error("ERROR opening socket");
        server = gethostbyname("127.0.0.1");
        if (server == NULL) {
            fprintf(stderr,"ERROR, no such host\n");
            exit(0);
        }
        bzero((char *) &serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy((char *)server->h_addr,
              (char *)&serv_addr.sin_addr.s_addr,
              server->h_length);
        serv_addr.sin_port = htons(portno);
        if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
            error("ERROR connecting");



        ai = new AI();
        (*ai).distance();
    }

    ~Client(){
        freeaddrinfo(host_info_list);
        close(socketfd);
        delete ai;
    }

    bool startsWith(char c1[], char c2[]){
        int i=0;
        while(c2[i] != 0){
            if(c1[i]==0)
                return false;
            if(c1[i] != c2[i])
                return false;
            i++;
        }

        return true;
    }

    void substr(char c[], int pos, char* s){
        int i;
        for(i=pos; c[i]!=0; i++){
            s[i-pos] = c[i];
        }
        s[i-pos] = 0;
    }

    void play(){

        bzero(buffer,256);
        n = read(sockfd,buffer,255);

        if(startsWith(buffer, (char*)"WELCOME"))
            printf(buffer);

        string colour;
        if(buffer[9]=='l')
            colour="black";
        else
            colour="white";

        char* msg = new char[256];

        while(true){
            bzero(buffer,256);
            n = read(sockfd,buffer,255);
            //printf(buffer);

            if(startsWith(buffer, (char*)"VALID_MOVE"))
                cout << "Valid move, please wait" << endl;
            else if(startsWith(buffer, (char*)"OPPONENT_MOVE")){

                substr(buffer, 14, msg);

                ai->updateBoard(msg);
                cout << "Opponent move: " << msg << endl;
            }
            else if(startsWith(buffer, (char*)"VICTORY")){
                cout << "You win" << endl;
                break;
            }
            else if(startsWith(buffer, (char*)"DEFEAT")){
                cout << "You lose" <<endl;
                break;
            }
            else if(startsWith(buffer, (char*)"TIE")){
                cout << "You tied" << endl;
                break;
            }
            else if(startsWith(buffer, (char*)"YOUR_TURN")){
                cout << "YOUR_TURN branch" << endl;
                string move = ai->generateNextMove(colour, 3);
                cout << "Your move is: " << move << endl;

                int i;
                for(i=0;i<8; i++){
                    msg[i] = move.at(i);
                }
                msg[i] = 0;

                sprintf(buffer, "MOVE %s\n", msg);

                std::this_thread::sleep_for(std::chrono::milliseconds(40));
                n = write(sockfd,buffer,strlen(buffer));

                ai->updateBoard(move);
            }
            else if(startsWith(buffer, (char*)"TIMEOUT")){
                cout << "Time out" << endl;
                break;
            }
            else if(startsWith(buffer, (char*)"MESSAGE")){
                substr(buffer, 8, msg);
                cout << msg << endl;
            }

        }
        close(sockfd);
    }
};

int main()
    {
        const char serverAddr[]="127.0.0.1";
        const char port[]="8901";
    Client * client = new Client(serverAddr, port);
    client->play();
        delete client;
    return 0;
    }

P.S。这是我的第一篇文章,如果我不由自主地忘记提供其他信息,请表示宽恕。谢谢。

1 个答案:

答案 0 :(得分:0)

对于我所看到的,当您使用

执行套接字读取时,您会理所当然地认为这是理所当然的
n = read(sockfd,buffer,255);

你似乎确信你总是收到一个完整的命令,但想想如果你只收到你的TU&#34;会发生什么?而不是&#34;你的转动&#34; 你总是清理缓冲区和你收到的下一个循环&#34; RN&#34;所以你永远不会处理命令,服务器仍在等待你的移动。

您应该做的是仅在收到完全有意义的命令时清理缓冲区。

如果取消注释:

 //printf(buffer);

您可以检查我的理论是否正确。