私はソケットプログラミングに比較的慣れていないので、ご容赦ください。
特定のプロトコル (区切り文字、「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 を使用しません。また、最初にフォークを使用せずにこの単純な推測ゲームをプルした後、フォーク機能を備えた同様のことを行います。
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:
クライアントからのユーザーがまだ何も送信していないときに、クライアントから送信されていることを確認しました。