Отправка буфера клавиатуры через Winsock - PullRequest
1 голос
/ 02 апреля 2011

Теперь я новичок в WINSOCKs и не очень бегло говорю на C ++, так что терпите меня. Я написал классы NetworkServer и NetworkClient, в основном основанные на руководствах по MSDN. Клиент будет отправлять серверу массив символов размером 256, содержащий состояние каждой стандартной кнопки клавиатуры (0 означает, что клавиша не нажата, 1 означает, что она нажата).

При запуске кода я сначала запускаю сервер, а затем клиент. Они нормально соединяются друг с другом. Затем вызывается клиент для отправки буфера клавиатуры. Буфер отправлен, но сервер зависает после:

receiveResult = recv(theClient, buffer, sizeof(buffer), 0);

Переменная «keys» в каждом классе является ключом char [256] для хранения каждого из состояний клавиш.

Ниже приведен цикл, который происходит после запуска NetworkServer:

char buffer[256];
int receiveResult, sendResult;

// Receive from the client
do
{
    receiveResult = recv(theClient, buffer, sizeof(buffer), 0);
    if (receiveResult > 0 )
    {
        sendResult = send(theClient, buffer, receiveResult, 0);
        if (sendResult == SOCKET_ERROR)
        {
            sendResult = WSAGetLastError();
            JBS::reportSocketError(nret, "server send()");
            closesocket(theClient);
            WSACleanup();
            return;
        }
        else
        {
            memcpy(keys, buffer, sizeof(keys));
        }
    }

    else if (receiveResult == 0)
        cout << "Server closing." << endl;
    else
    {
        receiveResult = WSAGetLastError();
        JBS::reportSocketError(nret, "server receive()");
        closesocket(theClient);
        WSACleanup();
        return;
    }
} while (receiveResult > 0);

А вот метод отправки NetworkClient:

char buffer[256];
memcpy(buffer, keys, sizeof(buffer));

nret = send(theSocket, buffer, sizeof(buffer),0);
if (nret == SOCKET_ERROR)
{
    nret = WSAGetLastError();
    JBS::reportSocketError(nret, "client send()");
    closesocket(theSocket);
    WSACleanup();
} 
do
{   
    char buff[256];
    nret = recv(theSocket, buff, sizeof(buff), 0);
    if (nret > 0)
    {
        memcpy(keys, buff, sizeof(keys));
    }
    else if (nret == 0)
        cout << "Server connection closed" << endl;
    else
    {
        nret = WSAGetLastError();
        JBS::reportSocketError(nret, "client receive()");
        closesocket(theSocket);
        WSACleanup();
    }

} while (nret > 0);

Как я уже сказал, между клиентом и сервером устанавливается соединение, но принимающая часть процесса, похоже, не работает. Любая помощь будет оценена.

Метод запуска NetworkClient:

sockVersion = MAKEWORD(1, 1);

// Initialize Winsock as before
WSAStartup(sockVersion, &wsaData);

// Store information about the server
LPHOSTENT hostEntry;

hostEntry = gethostbyname(serverAddress);     // Specifying the server by its name;

if (!hostEntry) {
    nret = WSAGetLastError();
    JBS::reportSocketError(nret, "client gethostbyname()");         // Report the error as before
    closesocket(theSocket);
    WSACleanup();
}

// Create the socket
theSocket = socket(AF_INET,                      // Go over TCP/IP
    SOCK_STREAM,                  // This is a stream-oriented socket
    IPPROTO_TCP);                 // Use TCP rather than UDP

if (theSocket == INVALID_SOCKET) {
    nret = WSAGetLastError();
    JBS::reportSocketError(nret, "client socket()");
    closesocket(theSocket);
    WSACleanup();
}

// Fill a SOCKADDR_IN struct with address information
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);
serverInfo.sin_port = htons(PORT);              // Change to network-byte order and
                                                // insert into port field

// Connect to the server
nret = connect(theSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));

if (nret == SOCKET_ERROR) 
{
    nret = WSAGetLastError();
    JBS::reportSocketError(nret, "client connect()");
    closesocket(theSocket);
    WSACleanup();
}
// Successfully connected!
started = true;

Ответы [ 2 ]

3 голосов
/ 02 апреля 2011

в коде клиента вы написали:

char buff[256];
nret = recv(theSocket, buff, (int)strlen(buff), 0);

это означает, что вы хотите получать данные в буфер, длина которого составляет strlen(buff).к сожалению, strlen() возвращает длину строки внутри буфера, то есть длину данных перед любым символом NUL внутри буфера.ваш компилятор был достаточно умен, чтобы инициализировать buff символами NUL, поэтому strlen(buf) возвращает 0, что означает, что вы хотите получить 0 байтов данных.таким образом, recv() ничего не получает.

что вы имели в виду:

nret = recv(theSocket, buff, sizeof(buff), 0);

(если бы вы попытались скомпилировать вашу программу с помощью Release Release, она бы сработала, потому что buff не было бы инициализированои strlen() вернул бы довольно случайный результат, из-за которого программа получила бы доступ к недопустимому адресу памяти ...)

Я должен добавить, что способ объявления вашего буфера неудачен:у вас есть массив логических значений (значение 1 или 0 в зависимости от состояния ключей).логическое значение не является символомстрогая декларация должна быть bool buff[256] ...

0 голосов
/ 02 апреля 2011

Проблема закончилась тем, как я присваивал значения в keyBuffer.Я делал

void key(unsigned char key, int x, int y)
{
    player.keyDown[key] = 1;
}

Вместо

void key(unsigned char key, int x, int y)
{
    player.keyDown[key] = '1';
}
...