通过Winsock发送键盘缓冲区

时间:2011-04-02 07:23:16

标签: c++ winsock

现在我是WINSOCK的新手,并不是超级流利的C ++,所以请耐心等待。我编写了一个NetworkServer和NetworkClient类,主要基于MSDN教程。客户端将向服务器发送一个大小为256的char数组,其中包含每个标准键盘按钮的状态(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 个答案:

答案 0 :(得分:3)

在客户端代码中,您写道:

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

这意味着您希望将数据接收到长度为strlen(buff)的缓冲区中。遗憾的是,strlen()返回缓冲区内字符串的长度,即缓冲区内任何NUL字符之前的数据长度。你的编译器非常聪明,可以使用NUL字符初始化buff,因此strlen(buf)返回0,这意味着你想要接收0字节的数据。因此,recv()没有收到任何东西。

你的意思是:

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

(如果你尝试使用Release版本编译你的程序,它会很快崩溃,因为buff将不会被初始化,而strlen()会返回一个相当随机的结果会导致程序访问无效的内存地址......)

我应该补充一点,你声明缓冲区的方式很不幸:你有一个布尔数组(值1或0,取决于键的状态)。布尔值不是char。严格的声明应该是bool buff[256] ......

答案 1 :(得分:0)

问题最终是我在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';
}