2013-03-18 33 views
0

我对套接字编程比较陌生,所以请耐心等待。使用C编程使用套接字编程的猜测整数游戏

我想使用具有特定协议(分隔符,“H”,“L”,“O”)的套接字编程做一个简单的猜测整数游戏。

我不知道为什么客户端重新发送原始空白数据,当客户端用户还没有输入任何猜测整数。

下面是server.c文件的部分:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <time.h> /* time for randomizer*/ 


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

int main(int argc, char *argv[]) 
{ 
    int sockfd, newsockfd, portno, n; 
    socklen_t clilen; 
    char buffer[256]; 
    struct sockaddr_in serv_addr, cli_addr; 

    int GuessedInteger, integerRandom, serverFlagCorrect; 
    char charGuess[4], answerServer[1]; 
    char* delimiter = "\\n"; 

    /** initialization of variables **/ 
    serverFlagCorrect = 0; 

    /** generate random integer from 1 to 100 **/ 
    srand (time(NULL)); 
    integerRandom = (rand() % 100) + 1; 

    printf("This is the random integer : %d \n", integerRandom); 

    if (argc < 2) { 
     fprintf(stderr,"ERROR, no port provided\n"); 
     exit(1); 
    } 

    // Creates the socket socket() --> endpoints of sockets 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    // Creates the socket socket() --> endpoints of sockets 

    // assign unique new address 
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    portno = atoi(argv[1]); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = INADDR_ANY; 
    serv_addr.sin_port = htons(portno); 

    if (bind(sockfd, (struct sockaddr *) &serv_addr, 
      sizeof(serv_addr)) < 0) 
      error("ERROR on binding"); 
    // assign unique new address 

    // wait for a connection 
    listen(sockfd,1); 
    // wait for a connection 

    // accepts the connection 
    clilen = sizeof(cli_addr); 
    newsockfd = accept(sockfd, 
       (struct sockaddr *) &cli_addr, 
       &clilen); 
    if (newsockfd < 0) 
     error("ERROR on accept"); 
    // accepts the connection 

    while (serverFlagCorrect != 1) 
    { 

     // reads the data being received 
     bzero(buffer,256); 
     n = read(newsockfd,buffer,255); 
     if (n < 0) error("ERROR reading from socket"); 
     // reads the data being received 

     printf("Buffer from client: <%s>\n", buffer); 
     memcpy(charGuess, buffer, sizeof(charGuess)); 
     printf("Message from client in charGuess: <%s>\n", charGuess); 

     /* Put if statement here for error out if no \n at the end */ 
     int len = strlen(charGuess); 
     const char *last_two = &charGuess[len-2]; 

     printf("Last two characters of charGuess: <%s>\n", last_two); 

     if (strncmp (last_two, delimiter, 2)) 
      error (" ERROR Wrong protocol received"); 

     /** process the string to integer for server comparison **/ 
     GuessedInteger = atoi(charGuess); 
     printf("Guessed Integer : %d \n", GuessedInteger); 

     /** Server response for comparison**/ 
     if (GuessedInteger > integerRandom) 
      memcpy(&answerServer, "L", sizeof(answerServer)); 
     else if (GuessedInteger < integerRandom) 
      memcpy(&answerServer, "H", sizeof(answerServer)); 
     else if (GuessedInteger == integerRandom) 
      { 
       serverFlagCorrect = 1; 
       memcpy(&answerServer, "O", sizeof(answerServer)); 
      } 
     printf("Value of answerServer: %c\n", *answerServer); 
     /** Server response for comparison**/ 

     // sends the answer 
     n = write(newsockfd, answerServer, 1); 
     if (newsockfd < 0) 
      error("ERROR on accept"); 
     // sends the answer 

     // closes what was sent 
     close(newsockfd); 
     // closes what was sent 

    }   

    //closes the socket if random integer was found 
    close(sockfd); 

    return 0; 
} 

及以下的client.c文件:

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <netdb.h> 

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

int main(int argc, char *argv[]) 
{ 
    int sockfd, portno, n; 
    struct sockaddr_in serv_addr; 
    struct hostent *server; 
    char buffer[1024]; 

    int integerGuess, clientFlagCorrect; 
    int numberOfTries; 
    char charGuess[1024], answerServer[1]; 
    char* delimiter = "\\n"; 


    if (argc < 3) { 
     fprintf(stderr,"usage %s hostname port\n", argv[0]); 
     exit(0); 
    } 
    portno = atoi(argv[2]); 

    // Creates the socket socket() --> endpoints of sockets 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (sockfd < 0) 
     error("ERROR opening socket"); 
    // Creates the socket socket() --> endpoints of sockets 

    server = gethostbyname(argv[1]); 
    if (server == NULL) { 
     fprintf(stderr,"ERROR, no such host\n"); 
     exit(0); 
    } 

    // connects to the service in connect() 
    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"); 
    // connects to the service 


    /** initialization of variables **/ 
    clientFlagCorrect = 0; 
    numberOfTries = 0; 

    while (clientFlagCorrect != 1) 
    { 
     numberOfTries = numberOfTries + 1; 

     /** initialization of variables **/ 
     integerGuess = 0; 
     memset(charGuess, 0, sizeof(charGuess)); 

     // ask the user for the guessed number 
     printf("Guess: "); 
     bzero(buffer,sizeof(buffer)); 
     fgets(buffer,sizeof(buffer)-1,stdin); 
     printf("Buffer to be processed : <%s>\n", buffer); 
     // ask the user for the guessed number 

     /** process the integer to string and add a delimiter **/ 
     integerGuess = atoi(buffer); 
     printf("integerGuess : <%d> \n", integerGuess); 
     sprintf(charGuess, "%d", integerGuess);  
     strcat(charGuess, delimiter); 
     printf("String Guess : <%s> \n", charGuess); 

     memset(buffer,0,sizeof(buffer)); 
     memcpy(buffer, charGuess, sizeof(charGuess)); 
     printf("Buffer to send : <%s>\n",buffer); 
     /** process the integer to string and add a delimiter **/ 

     // send the string that was processed 
     n = write(sockfd,buffer,strlen(buffer)); 
     if (n < 0) 
      error("ERROR writing to socket"); 
     // send the string that was processed 

     // reads the data being received 
     bzero(buffer,256); 
     n = read(sockfd,buffer,255); 
     if (n < 0) 
      error("ERROR reading from socket"); 
     // reads the data being received 

     printf("Buffer received : <%s>\n",buffer); 

     memcpy(&answerServer, buffer, sizeof(answerServer)); 
     printf ("Value of answerServer : <%c> \n", *answerServer); 

     /** Client response **/ 
     if (strncmp (& answerServer[0],"L",sizeof(answerServer)) == 0) 
      printf("Lower \n"); 
     else if (strncmp (& answerServer[0],"H",sizeof(answerServer)) == 0) 
      printf("Higher \n"); 
     else if (strncmp (& answerServer[0],"O",sizeof(answerServer)) == 0) 
      { 
       printf("Correct \n"); 
       clientFlagCorrect = 1; 
      } 
     else 
      error("ERROR Wrong message received"); 

    } 

    printf ("Tries: %d \n", numberOfTries); 

    printf("%s\n",buffer); 

    close(sockfd); 
    return 0; 
} 

在修复这个相当恼人的错误,我一直在尝试任何意见修理半天?

想到我提到(如果它很重要),我不打算在这里使用叉。在我没有先使用fork的情况下抽出这个简单的猜谜游戏之后,我也会做类似fork函数的事情。

EDIT1:添加了什么我通过终端获得(和抱歉,我不认为这是很好的,我删除了服务器和客户端的代码的某些部分):

服务器端:

$ gcc -Wall -o server server.c 
$ ./server 5678 
This is the random integer : 66 
Buffer from client: <20\n> 
Message from client in charGuess: <20\n> 
Last two characters of charGuess: <\n> 
Guessed Integer : 20 
Value of answerServer: H 
ERROR reading from socket: Bad file descriptor 
$ 

客户端:

$ ./client3 localhost 5678 
Guess: 20 
Buffer to be processed : <20 
> 
integerGuess : <20> 
String Guess : <20\n> 
Buffer to send : <20\n> 
Buffer received : <H> 
Value of answerServer : <H> 
Higher 
Guess: 

我检查了,它已经从客户端时从客户端的用户还没有发送任何数据尚未发送。

+0

对于SO来说,编码这个长度肯定太局限了。 (请阅读[常见问题](http://stackoverflow.com/faq),询问不同类型的问题) – 2013-03-18 14:50:03

+0

@lc。,lemme尝试将问题分解到我面临问题的部分。并且还可以添加通过终端获得的结果。 – AisIceEyes 2013-03-18 14:59:01

+0

@ lc.-我没有修改上面的代码,只是添加了我在终端窗口中获​​得的内容。希望能让事情变得更清晰。 – AisIceEyes 2013-03-18 15:07:19

回答

2

printf调试输出已经给出了错误的指示。考虑看看从你偶然发现的服务器报告的最后一行:

ERROR reading from socket: Bad file descriptor 

此问题是由试图从已经关闭的文件进行读取。为了稍微减轻你的例子的代码丛林,我只是复制了相关的部分。希望这样的错误会更容易辨认:

while (serverFlagCorrect != 1) 
{ 
    // ... 

    /* reads pretty well in the first run */ 
    n = read(newsockfd,buffer,255); 

    // ... 

    close(newsockfd); 
    /* oops - there won't be any filedescriptor to read from in the second run */ 
} 
/* close() should be placed here instead */ 

虽然一切都只是在进入循环newsockfd不会是一个有效的文件描述符任何更多的你关闭后,后是在第一次运行的罚款。将close (newsockfd)行移动到指定位置即可解决问题。

+0

哦。我现在明白了。关闭应该在while循环之外。谢谢! – AisIceEyes 2013-03-18 22:27:12

+0

我实际上认为每次read()运行时,它都会被唤醒,因为它仍然处于监听状态。我想,我明白错误。再次感谢! – AisIceEyes 2013-03-18 22:35:45