Now I'm new to the WINSOCKs, and not super fluent in C++, so bear with me. I've written a NetworkServer and NetworkClient class, mostly based off of the MSDN tutorials. The client will be sending the server a char array of size 256, containing the state of each standard keyboard button (0 means the key is not being pressed, 1 means it is being pressed).
When running the code, I first start the server, and then the client. They connect to each other fine. The client is then called to send the keyboard buffer. The buffer is sent, but the server hangs after:
receiveResult = recv(theClient, buffer, sizeof(buffer), 0);
The "keys" variable in each class is a char keys[256] to hold each of the key states.
Below is the loop that occurs once a NetworkServer has been started:
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);
And here is the NetworkClient send method:
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);
As I said, the connection is being established between client and server, but the receiving part of the process doesn't seem to be working. Any help would be appreciated.
NetworkClient's start method:
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 t开发者_StackOverflow社区o 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;
in the client code, you wrote:
char buff[256];
nret = recv(theSocket, buff, (int)strlen(buff), 0);
this means that you want to receive data into a buffer which length is strlen(buff)
. unfortunately, strlen()
returns the length of the string inside the buffer, that is the length of data before any NUL character inside the buffer. your compiler was smart enough to initialize buff
with NUL characters, thus strlen(buf)
returns 0, which means that you want to receive 0 bytes of data. thus, recv()
does not receive anything.
what you meant is:
nret = recv(theSocket, buff, sizeof(buff), 0);
(if you tried compiling your program using the Release build, it would have crashed happily, because buff
would then not be initialized, and strlen()
would have returned a pretty random result which would have caused the program to access an invalid memory address...)
i should add that the way you declare your buffer is unfortunate: you have an array of booleans (value 1 or 0 depending of the state of keys). a boolean is not a char. a strict declaration should be bool buff[256]
...
Problem ended up being how I was assigning the values in the keyBuffer. I was doing
void key(unsigned char key, int x, int y)
{
player.keyDown[key] = 1;
}
Instead of
void key(unsigned char key, int x, int y)
{
player.keyDown[key] = '1';
}
精彩评论