2011-04-02 122 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