Zdravím, mám problém s Windows socketama. Mám následující kód klienta a serveru.
client.cpp:
#define WIN32_LEAN_AND_MEAN
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
int main() {
WSADATA wsaData;
SOCKET connectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL, *ptr = NULL, hints;
int iResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0) {
std::cout << "WSAStartup failed with error:" << iResult;
return 1;
} else {
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
int addrInfo = getaddrinfo("127.0.0.1", "27015", &hints, &result);
if(addrInfo != 0) {
std::cout << "getaddrinfo failed with error:" << addrInfo;
WSACleanup();
return 1;
} else {
// Create a SOCKET for connecting to server
connectSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (connectSocket == INVALID_SOCKET) {
std::cout << "socket failed with error:" << WSAGetLastError();
WSACleanup();
return 1;
} else {
// Connect to server.
iResult = connect(connectSocket, result->ai_addr, (int)result->ai_addrlen);
if(iResult == SOCKET_ERROR) {
closesocket(connectSocket);
connectSocket = INVALID_SOCKET;
} else {
freeaddrinfo(result);
if(connectSocket == INVALID_SOCKET) {
std::cout << "Unable to connect to server!";
WSACleanup();
return 1;
} else {
char sbb[] = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345612345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234561234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456";
char *sendbuf = sbb;
iResult = send(connectSocket, sendbuf, strlen(sendbuf), 0);
if(iResult == SOCKET_ERROR) {
std::cout << "send failed with error: " << WSAGetLastError();
closesocket(connectSocket);
WSACleanup();
return 1;
} else {
std::cout << "Bytes Sent: " << iResult << "\n";
// shutdown the connection since no more data will be sent
iResult = shutdown(connectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
std::cout << "shutdown failed with error: " << WSAGetLastError();
closesocket(connectSocket);
WSACleanup();
return 1;
} else {
//Receive until the peer closes the connection
int bufCounter = 0;
std::string receivedData;
do {
char recvBuf[256];
std::string recvBufString;
iResult = recv(connectSocket, recvBuf, 256, 0);
if(iResult > 0) {
bufCounter = bufCounter + iResult;
recvBufString = std::string(recvBuf);
std::cout << "\nPart recv bt: " << recvBufString.length() << "\n";
receivedData = receivedData + recvBufString;
} else if (iResult == 0) {
std::cout << "Connection closed" << "\n";
} else {
std::cout << "recv failed with error: " << WSAGetLastError() << "\n";
}
} while(iResult > 0);
std::cout << "\n\nBytes received: " << bufCounter << "\n";
std::cout << "Data received: " << receivedData << "\n";
// cleanup
closesocket(connectSocket);
WSACleanup();
}
}
}
}
}
}
}
return 0;
}
server.cpp:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
int main() {
WSADATA wsaData;
int iResult;
SOCKET listenSocket = INVALID_SOCKET;
SOCKET clientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
} else {
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, "27015", &hints, &result);
if(iResult != 0) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
} else {
// Create a SOCKET for connecting to server
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if(listenSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
} else {
// Setup the TCP listening socket
iResult = bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
if(iResult == SOCKET_ERROR) {
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(listenSocket);
WSACleanup();
return 1;
} else {
freeaddrinfo(result);
iResult = listen(listenSocket, SOMAXCONN);
if(iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return 1;
} else {
// Accept a client socket
clientSocket = accept(listenSocket, NULL, NULL);
if(clientSocket == INVALID_SOCKET) {
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(listenSocket);
WSACleanup();
return 1;
} else {
// No longer need server socket
closesocket(listenSocket);
//Receive until the peer closes the connection
int bufCounter = 0;
std::string receivedData;
do {
char recvBuf[256];
std::string recvBufString;
iResult = recv(clientSocket, recvBuf, 256, 0);
if(iResult > 0) {
bufCounter = bufCounter + iResult;
recvBufString = std::string(recvBuf);
std::cout << "\nPart recv bt: " << recvBufString.length() << "\n";
receivedData = receivedData + recvBufString;
} else if(iResult == 0) {
std::cout << "Connection closed" << "\n";
} else {
std::cout << "recv failed with error: " << WSAGetLastError() << "\n";
}
} while (iResult > 0);
std::cout << "\n\nBytes received: " << bufCounter << "\n";
std::cout << "Data received: " << receivedData << "\n";
// shutdown the connection since we're done
iResult = shutdown(clientSocket, SD_SEND);
if(iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(clientSocket);
WSACleanup();
return 1;
} else {
// cleanup
closesocket(clientSocket);
WSACleanup();
}
}
}
}
}
}
}
return 0;
}
Snažím se tedy poslat zprávu (viz. úryvek kódu níže) serveru o velikosti kódu 1024 bytů, který tu zprávu pošle klientovi zpátky. Soket hlásí, že se poslalo 1024 bytů (což sedí), ale když si vypíšu velikost jednotlivých chunků (který má dle soketu 256 bytů) tak jeho velikost je 267 (viz. výpis programu níže). Když vypíšu celou zprávu (sestavuji ji po dokončení příjmu), tak je u každého chunku pár bytů (267-256=11 navíc). Nechápu tedy proč tam jsou, když soket mi hlásí 1024 bytů odeslaných/přijatých na obou stranách (server to má odesílat zpátky klientu, tuto funkci jsem teď vynechal, ale mám ověřeno, že tento problém je i při odeslání zpět.
Zpráva, se kterou se manipuluje:
char sbb[] = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345612345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234561234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456";
Výpis client.cpp:
Bytes Sent: 1024
Connection closed
Bytes received: 0
Data received:
Výpis server.cpp:
Part recv bt: 267
Part recv bt: 267
Part recv bt: 267
Part recv bt: 267
Connection closed
Bytes received: 1024
Data received: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456╠╠╠╠╠╠╠╠ÇÇ≥1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456╠╠╠╠╠╠╠╠Ç≥1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456╠╠╠╠╠╠╠╠╨z≥1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456╠╠╠╠╠╠╠╠ÇÇ≥
Samozřejmě jsem i googlil a vygooglil to, že ve funkci send(), kde se uvádí parametr velikosti toho bufferu mám přidat +1 kvůli NULL znaku, (viz. ukázka kódu níže), avšak to můj problém také neřeší, akorát se pošle o byte víc, ale ty znaky tam stále jsou.
iResult = send(connectSocket, sendbuf, strlen(sendbuf) + 1, 0);