Сетевое программирование в Linux (1119562), страница 3
Текст из файла (страница 3)
This is a SERVER.\n");printf("Command line syntax: BCSrv [port number]\n");// Устанавливаем обработчикif (signal(SIGPIPE, &SigHandler) == SIG_ERR){fprintf(stderr, "Error: cannot set signal handler!\n");return 0;}// Порт по умолчаниюint Port = 1234;if (argc > 1) Port = atoi(argv[1]);printf("Using port #%d.\n", Port);// Создаём слушающее гнездоint s0 = socket(AF_INET, SOCK_STREAM, 0);if (s0 < 0){fprintf(stderr, "Error: cannot create a socket.\n");return 0;}6sockaddr_in MyAddr;memset(&MyAddr, 0, sizeof(sockaddr_in));MyAddr.sin_family = AF_INET;MyAddr.sin_port = htons(Port);MyAddr.sin_addr.s_addr = htonl(INADDR_ANY);// Привязываем его к адресуif (bind(s0, (sockaddr*) &MyAddr, sizeof(MyAddr)) < 0){fprintf(stderr, "Error: cannot bind a socket.\n");close(s0);return 0;}printf("Waiting for the client...\n");// Настраиваем гнездоlinger linger_opt = { 1, 0 };setsockopt(s0, SOL_SOCKET, SO_LINGER, &linger_opt, sizeof(linger_opt));// Слушаем...if (listen(s0, 1) < 0){fprintf(stderr, "Error: cannot listen on the socket.\n");close(s0);return 0;}// Кто-то подключился, принимаем соединениеsockaddr_in CliAddr;socklen_t AddrLen;int s1 = accept(s0, (struct sockaddr*) &CliAddr, &AddrLen);if (s1 < 0){fprintf(stderr, "Error: cannot accept connection.\n");return 0;}printf("Connection accepted\n");// Закрываем слуховое гнездоclose(s0);int MyNumber;int MyGuess;// Number of server// Guessed number of clientdo{printf("Enter number: ");scanf("%d", &MyNumber);} while (MyNumber < 1023 || MyNumber > 9876);int SendBuffer[MAX];int RecvBuffer[MAX];int TN = 0;// Основной цикл программыwhile (true){printf("=============================\nGuess opponent’s number: ");scanf("%d", &MyGuess); MyGuess = MyGuess % 10000; if (!MyGuess) break;TN++;SendBuffer[0] = MyNumber; // Our RIGHT number (Server)SendBuffer[1] = MyGuess; // Guessed number of clientwrite(s1, SendBuffer, MAX * sizeof(int));printf("Waiting for opponent’s reply...\n");if (!WaitMessage(s1, RecvBuffer)) break;int HisNumber = RecvBuffer[0]; // Right client’s numberint HisGuess = RecvBuffer[1];int B = 0; int C = 0;if (!GetAnswer(HisNumber, MyGuess, &B, &C)) { printf("Wrong number!!!\n"); break; }7printf("Opponent’s guess: %d.
Your try: %d bulls, %d cows.\n", HisGuess, B, C);if (HisGuess == MyNumber) printf("GAME OVER: Your opponent wins at the %d-th turn.", TN);if (HisNumber == MyGuess) printf("CONGRATULATIONS: You win at the %d-th turn!.", TN);}// Закрываем клиентское гнездоclose(s1);return 0;}bool WaitMessage(int Socket, int * Buffer){fd_set DSet;FD_ZERO(&DSet);FD_SET(Socket, &DSet);timeval tv;tv.tv_sec = 100;tv.tv_usec = 0;if (select(Socket+1, &DSet, 0, 0, &tv) > 0){read(Socket, Buffer, 1024);return true;}else{// Они что там, заснули, что-ли?printf("Connection timed out or other player fell asleep.\n");return false;}}bool GetAnswer(int N, int GN, int * B, int * C){int d0 = N % 10;N /= 10;int d1 = N % 10;N /= 10;int d2 = N % 10;N /= 10;int d3 = N % 10;if (d0 == d1 || d0 == d2 || d0 == d3 ||d1 == d2 || d1 == d3 || d2 == d3) return false;int gd0 =GN /= 10;int gd1 =GN /= 10;int gd2 =GN /= 10;int gd3 =GN % 10;GN % 10;GN % 10;GN % 10;if (gd0 == gd1 || gd0 == gd2 || gd0 == gd3 ||gd1 == gd2 || gd1 == gd3 || d2 == d3) return false;int b = 0; int c = 0;if (gd0 == d0) b++;if (gd1 == d1) b++;if (gd2 == d2) b++;if (gd3 == d3) b++;if ((gd0 != d0) && (gd0if ((gd1 != d1) && (gd1if ((gd2 != d2) && (gd2if ((gd3 != d3) && (gd3========d1d0d0d0||||||||gd0gd1gd2gd3========d2d2d1d1||||||||gd0gd1gd2gd3========d3))d3))d3))d2))*B = b; *C = c; return true;}// Могучий обработчик сетевого обломаvoid SigHandler(int SigID){printf("Broken pipe.
SID: %d", SigID);exit(-1);}8c++;c++;c++;c++;5.2.2. Клиентская частьЗдесь опущены комментарии для фрагментов кода, совпадающих с серверной частью.#include#include#include#include#include#include#include#include<signal.h><stdio.h><string.h><stdlib.h><unistd.h><sys/socket.h><netinet/in.h><netdb.h>const int MAX = 64;void SigHandler(int);bool WaitMessage(int Socket, int * Buffer);bool GetAnswer(int N, int GN, int * B, int * C);int main(int argc, char *argv[]){printf("Welcome to the game ’Bulls & Cows’.
This is a CLIENT.\n");printf("Command line syntax: BCCli [host address] [port number]\n");if (signal(SIGPIPE, &SigHandler) == SIG_ERR){fprintf(stderr, "Error: cannot set signal handler!\n");return 0;}int s0 = socket(AF_INET, SOCK_STREAM, 0);if (s0 < 0){fprintf(stderr, "Error: cannot create a socket.\n");return 0;}sockaddr_in SrvAddr;memset(&SrvAddr, 0, sizeof(SrvAddr));// Получение адреса сервераchar * HostName = "localhost";if (argc >= 2) HostName = argv[1];hostent * Host = gethostbyname(HostName);if (!Host){fprintf(stderr, "Error: cannot get host address.\n");close(s0);return 0;}SrvAddr.sin_family = AF_INET;int Port = 1234;if (argc >= 3) Port = atoi(argv[2]);SrvAddr.sin_port = htons(Port);// Заполняем адрес сервераmemmove(&(SrvAddr.sin_addr.s_addr), Host->h_addr_list[0], 4);printf("Connecting to %s...\n", HostName);// Подключаемся...if (connect(s0, (struct sockaddr*) &SrvAddr, sizeof(SrvAddr)) < 0){fprintf(stderr, "Error: cannot connect to remote host.\n");close(0);return 0;}printf("You are connected to server!");int MyNumber; // Number of serverint MyGuess; // Guessed number of clientdo9{printf("Enter number:");scanf("%d", &MyNumber);} while (MyNumber < 1023 || MyNumber > 9876);int SendBuffer[MAX];int RecvBuffer[MAX];int TN = 0;// Основной цикл программыwhile (true){printf("=============================\nGuess opponent’s number: ");scanf("%d", &MyGuess); MyGuess = MyGuess % 10000; if (!MyGuess) break;TN++;SendBuffer[0] = MyNumber; // Our RIGHT number (Server)SendBuffer[1] = MyGuess; // Guessed number of clientwrite(s1, SendBuffer, MAX * sizeof(int));printf("Waiting for opponent’s reply...\n");if (!WaitMessage(s1, RecvBuffer)) break;int HisNumber = RecvBuffer[0]; // Right client’s numberint HisGuess = RecvBuffer[1];int B = 0; int C = 0;if (!GetAnswer(HisNumber, MyGuess, &B, &C)) { printf("Wrong number!!!\n"); break; }printf("Opponent’s guess: %d.
Your try: %d bulls, %d cows.\n", HisGuess, B, C);if (HisGuess == MyNumber) printf("GAME OVER: Your opponent wins at the %d-th turn.", TN);if (HisNumber == MyGuess) printf("CONGRATULATIONS: You win at the %d-th turn!.", TN);}// Закрываем клиентское гнездоclose(s1);return 0;}// Здесь ещё должны быть функции WaitMessage, GetAnswer и SigHandler,// которые можно позаимствовать из серверной части, поскольку// они ничем не отличаются.10.