2011-04-02 131 views
1

现在我刚刚接触WINSOCKs,而不是C++中的超流利,请耐心等待。我写了一个NetworkServer和NetworkClient类,主要基于MSDN教程。客户端将向服务器发送大小为256的char数组,其中包含每个标准键盘按钮的状态(0表示未按键,1表示正在按下)。通过Winsock发送键盘缓冲区

运行代码时,我首先启动服务器,然后启动客户端。他们互相连接好。客户端然后被调用来发送键盘缓冲区。缓冲器被发送,但服务器挂起之后:

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

每个类中的“键”的变量是一个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; 

回答

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'; 
} 
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); 

(如果你试图编译使用发布版本的程序,它会高兴地崩溃,因为buff随后将不会被初始化,strlen()会很返回随机结果这会造成程序访问无效的内存地址...)

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

+0

好,我改变了这一切,但该方案仍是悬在同一地点。 – 131nary 2011-04-02 07:40:17

+0

@ 131nary,同样,你不应该在你的_client_代码中使用'strcpy_s(buffer,keys);'。 – sarnold 2011-04-02 07:43:20

+0

@sarnold什么是适当的替代? – 131nary 2011-04-02 07:45:16