2014-12-29 2 views
0

Я пытаюсь сделать шахматную игру через сокеты. Существует сервер, ответственный за отправку платы игрокам, получение ввода и ответа и т. Д. Я попытался создать клиент-сервер (фактически 2clients и server), но он не работает , Клиенты подключаются к серверу должным образом, но данные, которые опрошены, не исправляются. Например, я посылаю «E2-C3» от клиента; результат recv (на стороне сервера) всегда равен 0 или печатает мусор.отправка данных через сокет не работает

Клиент:

#define WIN32_LEAN_AND_MEAN 

#include <windows.h> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 
#include <string> 
#include <sys/types.h> 

// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib 
#pragma comment (lib, "Ws2_32.lib") 
#pragma comment (lib, "Mswsock.lib") 
#pragma comment (lib, "AdvApi32.lib") 

using namespace std; 


#define SERVER_IP "1.1.1.1" 
#define SERVER_PORT 8888 
#define BUFFER_SIZE 1024 

// server side 
#define INVALID_MOVE 00 
#define PLEASE_ENTER_A_MOVE 15 
#define PRINT_BOARD 20 
#define END_GAME 30 

// client side 
#define MOVE 10 

int __cdecl main() 
{ 
    WSADATA info; 
    int errorDATA; // configuriation 
    int socketCreate; // create the socket - empty 
    SOCKADDR_IN ClientService; // configuriation (stage 3) - data of the server. 
    int connectResult; 
    char sendBuf[1024], recvbuf[1024]; 
    int iResult; 

    /*Configuration*/ 
    errorDATA = WSAStartup(MAKEWORD(2, 2), &info); 
    if (errorDATA == INVALID_SOCKET) 
    { 
     printf("WSAStartup failed with error : %d\n", errorDATA); 
     return -1; 
    } 
    /*Create empty socket*/ 
    socketCreate = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // creating the socket "Clean - empty" 
    if (socketCreate == INVALID_SOCKET) 
    { 
     printf("Error number %d in creating socket!\n", WSAGetLastError()); 
     return -1; 
    } 
    printf("Creating socket SUCCEEDED!\n"); 

    /*Confugirate the created socket*/ 
    ClientService.sin_family = AF_INET; 
    ClientService.sin_addr.s_addr = inet_addr(SERVER_IP); // server's ip 
    ClientService.sin_port = htons(SERVER_PORT); 

    /*Asking for connection*/ 
    connectResult = connect(socketCreate, (struct sockaddr*) &ClientService, sizeof(ClientService)); 

    while (1) 
    { 
     cout << "Please enter a move : " << endl; 
     cin >> sendBuf; 
     iResult = send(socketCreate, sendBuf, (int)strlen(sendBuf), 0); 
     if (iResult == SOCKET_ERROR) { 
      printf("send failed with error: %d\n", WSAGetLastError()); 
      closesocket(socketCreate); 
      WSACleanup(); 
      return 1; 
     } 
     // MOVE 
     iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0); 
     if (iResult > 0) 
     { 
      if (recvbuf[0] == '0' && recvbuf[1] == '0') 
      { 
       cout << "You've entered an illegal move. Please try again." << endl; 
       continue; 
      } 
      else if (recvbuf[0] == '2' && recvbuf[1] == '0') 
      { 
       // print the board. 
       bool keepGoing = 0; 
       do 
       { 
        iResult = recv(socketCreate, recvbuf, strlen(recvbuf), 0); 
        if (iResult > 0) 
        { 
         if (recvbuf[0] == '1' && recvbuf[1] == '5') 
         { 
          keepGoing = true; 
          continue; 
         } 
        } 
       } while (!keepGoing); 
      } 
     } 
     else if (iResult == 0) 
      printf("Connection closed\n"); 
     else 
      printf("recv failed with error: %d\n", WSAGetLastError()); 
    } 


    printf("Bytes Sent: %ld\n", iResult); 

    // shutdown the connection since no more data will be sent 
    iResult = shutdown(socketCreate, SD_SEND); 
    if (iResult == SOCKET_ERROR) { 
     printf("shutdown failed with error: %d\n", WSAGetLastError()); 
     closesocket(socketCreate); 
     WSACleanup(); 
     return 1; 
    } 


    // cleanup 
    closesocket(socketCreate); 
    WSACleanup(); 

    cin.get(); 
    system("pause"); 
    return 0; 
} 

сервер:

#include <iostream> 
#include <winsock2.h> 
#include <string> 
#include <windows.h> 
#pragma comment(lib,"ws2_32.lib") 

#define MAX_NUMBER_OF_PLAYERS 1 
#define BUFFER_SIZE 1024 
#define LIMIT 1 

// server side 
#define INVALID_MOVE 00 
#define PLEASE_ENTER_A_MOVE 15 
#define PRINT_BOARD 20 
#define END_GAME 30 

// client side 
#define MOVE 10 


using namespace std; 

int main() 
{ 
    WSADATA WsaDat; 
    SOCKET clientsock[2]; 
    int minsock = 0; 
    int numsocks = MAX_NUMBER_OF_PLAYERS; 
    if (WSAStartup(MAKEWORD(2, 2), &WsaDat) != 0) 
    { 
     std::cout << "WSA Initialization failed!\r\n"; 
     WSACleanup(); 
     system("PAUSE"); 
     return 0; 
    } 

    SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (serverSocket == INVALID_SOCKET) 
    { 
     std::cout << "Socket creation failed.\r\n"; 
     WSACleanup(); 
     system("PAUSE"); 
     return 0; 
    } 

    SOCKADDR_IN serverInf; 
    serverInf.sin_family = AF_INET; 
    serverInf.sin_addr.s_addr = INADDR_ANY; 
    serverInf.sin_port = htons(8888); 

    if (bind(serverSocket, (SOCKADDR*)(&serverInf), sizeof(serverInf)) == SOCKET_ERROR) 
    { 
     std::cout << "Unable to bind socket!\r\n"; 
     WSACleanup(); 
     system("PAUSE"); 
     return 0; 
    } 

    listen(serverSocket, 5); 


    clientsock[0] = accept(serverSocket, NULL, NULL); 
    cout << "Client 1 has connected." << endl; 
    clientsock[1] = accept(serverSocket, NULL, NULL); 
    cout << "Client 2 has connected." << endl; 

    for (int i = 0; i < 2; i++) 
    { 
     cout << clientsock[i] << endl; 
    } 

    // If iMode!=0, non-blocking mode is enabled. 
    u_long iMode = 1; 
    ioctlsocket(serverSocket, FIONBIO, &iMode); 


    char client1_buffer[BUFFER_SIZE]; 
    char client2_buffer[BUFFER_SIZE]; 
    char* clientBuffer; 
    // until there isn't a mate. 
    bool gameRunning = true; 
    // user represents if it's user1 (0), or user2(1) 
    bool user = 0; 


    while (gameRunning) 
    { 
     if (!user) 
      clientBuffer = client1_buffer; 
     else 
      clientBuffer = client2_buffer; 

     int in = recv(clientsock[0], client1_buffer, 0, 0); 
     cout << in << endl; 
     if (in > 0) 
     { 
       // CHECKS 
       // MOVE COMMAND 
       // IF worked, send the board to both clients. if current user = 1 ==> do user to 0 | if the user = 0 => do user to 11 
       // ELSE, send the current client (clientsock[user]) Error message and ask for a command again. 
      cout << client1_buffer << endl; 
       cout << " IN RECV"; 
       char* szMessage = "15"; 
       send(clientsock[0], szMessage, strlen(szMessage), 0); 
     } 
     else if (in == 0) 
     { 
      // The connection has closed. 
      // REMEMBER : SAVE THE GAME SITUATION. 
     } 
     else 
     { 
      printf("recv failed: %d\n", WSAGetLastError()); 
      // SEND ERROR MESSAGE TO BOTH CLIENTS 
     } 


    } 
    // Shutdown our socket 
    shutdown(serverSocket, SD_SEND); 

    // Close our socket entirely 
    closesocket(serverSocket); 

    WSACleanup(); 
    system("pause"); 
    return 0; 
} 

ответ

2

Проблема заключается в том

strlen(recvbuf) 

Вы, вероятно, означает

sizeof(recvbuf) 

strlen (recvbuf) не имеет смысла до вы получили данные, потому что ваш буфер содержит только мусор, поэтому strlen() - это просто плохой генератор случайных чисел. strlen (recvbuf) будет иметь смысл после, вы получили данные, если бы вы убедились, что они были заполнены 0. Это не так, вы можете использовать возвращаемое значение recv(), чтобы узнать, сколько байтов вы получили.

4

Что сказал Ганс. плюс к этому:

int in = recv(clientsock[0], client1_buffer, 0, 0); 

Вы, вероятно, хотите сказать, что это:

int in = recv(clientsock[0], client1_buffer, BUFFER_SIZE, 0); 

Кроме того, вы делаете фундаментальную ошибку, что многие люди делают с сокетами. Вы предполагаете, что ваш вызов recv на ваш сервер вернет так много байтов, которые были переданы соответствующему вызову send клиентом. Фрагментация, сегментация и другие сетевые материалы могут привести к получению только частичной суммы сообщения, которое было отправлено по вызову send другого узла. (Следовательно, TCP - это протокол потока, как говорится).

Вы должны внимательно проверить возвращаемое значение от recv. Напишите свой код так, как будто отправитель должен был отправлять только 1 байт за раз. Вы должны помещать разделители между вашими сообщениями (нулевой символ в порядке) и loop on recv, пока не получите полное сообщение. В противном случае, кажется, что на вашем собственном ПК и в локальной подсети все будет нормально работать, если вы будете подключены к Интернету.

+0

Спасибо! Еще одна проблема, с которой я столкнулся, когда сервер ждет сообщений и не получает его, печатает 0. Как я могу его исправить? – Guy

+0

Для начала у вас включен режим блокировки: 'ioctlsocket (serverSocket, FIONBIO, & iMode);' Сделайте эту строку и посмотрите на использование «select» для контроля обоих сокетов для ввода. http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141% 28v = vs.85% 29.aspx – selbie

+0

Итак, с помощью этой функции я могу разговаривать через 2sockets без потоков? – Guy

2

В изменении файла сервера

int in = recv(clientsock[0], client1_buffer, 0,0); 

в

int in = recv(clientsock[0], client1_buffer, 1024,0); 

изменение длины дня, чтобы получить

Смежные вопросы