我正在用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。这是我的第一篇文章,如果我不由自主地忘记提供其他信息,请表示宽恕。谢谢。
答案 0 :(得分:0)
对于我所看到的,当您使用
执行套接字读取时,您会理所当然地认为这是理所当然的n = read(sockfd,buffer,255);
你似乎确信你总是收到一个完整的命令,但想想如果你只收到你的TU&#34;会发生什么?而不是&#34;你的转动&#34; 你总是清理缓冲区和你收到的下一个循环&#34; RN&#34;所以你永远不会处理命令,服务器仍在等待你的移动。
您应该做的是仅在收到完全有意义的命令时清理缓冲区。
如果取消注释:
//printf(buffer);
您可以检查我的理论是否正确。