我必須編寫一個使用UNIX域套接字的"Sea Battle"遊戲作爲分配。服務器和客戶端在同一臺機器上,只是爲了瞭解IPC。UNIX域套接字讀取()總是得到錯誤的值
每艘船都有一個尺寸。
我遇到了一個我無法解決的問題,我希望你有一個想法。首先我知道read(),write(),select(),...有一個返回值,我檢查它們。但是我會讓他們忘記代碼更好的可讀性。而且我還會留下其他不必要的代碼。
服務器和客戶端幾乎是相同的,除了連接(這不是問題),他們處於相反的狀態,這是檢查turn == 0並轉!= 0。我再次寫一個。
所以我的問題:在其他讀取功能是非阻塞的,因爲控制檯輸入在if。我試圖用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;
}
下面的例子:
假設的船都設置這樣的:(X代表船,O代表進攻這是不是一艘船)
server: client:
A B C D E A B C D E
1 X 1 X
2 X 2 X
3 X 3 X
4 X 4 X
5 X 5 X
遊戲開始時你會看到一塊代表敵方主板和服務器攻擊場的白板(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
這顯然是錯誤的,但它使用敵人的字段(1,A)的值將其使用來自服務器輸入字段的值。比方說,這將創下船客戶端攻擊(1,A),但由於最後一攻沒打船的輸出是:
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,雖然您預計要讀取2個字節,但該怎麼辦? – usr
感謝您的回覆。正如我在主題開始時提到的那樣,我檢查了他們,我只是把它們留在這裏,它在這裏更好。 – user2962094
我有麻煩尋找代碼示例中存在明顯的「錯誤」錯誤的真正的錯誤。請在您的腦海中發佈完整版本,100%正確。很多人濫用'read'(因爲它很難正確使用),而且我無法從這段代碼中看出你的使用是否正確。在這種情況下我怎麼能找到你的問題?你甚至會說這個問題就在這一行!我如何查看不顯示的代碼行? – usr