Winsock 2 - Divné znaky ve zprávě – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Winsock 2 - Divné znaky ve zprávě – C / C++ – Fórum – Programujte.comWinsock 2 - Divné znaky ve zprávě – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
richard.zavodny0
Návštěvník
9. 4. 2018   #1
-
0
-

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);
Nahlásit jako SPAM
IP: 89.24.189.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
Řešení
gna
~ Anonymní uživatel
1891 příspěvků
9. 4. 2018   #2
-
0
-
Vyřešeno Nejlepší odpověď

   

recvBufString = std::string(recvBuf, iResult);
Nahlásit jako SPAM
IP: 213.211.51.–
richard.zavodny0
Návštěvník
9. 4. 2018   #3
-
0
-

#2 gna
Super, díky moc. Nečekal jsem, že to bude tak banální. :) Sice stále nechápu, proč se tam ty "bajty" navíc přimíchávají, ale to můj problém je vyřešen.

Nahlásit jako SPAM
IP: 89.24.189.–
Programátor, Kóder, Grafický designér, Kritik, zastánce Open-Source a Linuxu.
Radek Chalupa
~ Redaktor
+1
Super člen
9. 4. 2018   #4
-
0
-

#3 richard.zavodny
Takhle ze zběžného pohledu myslím že je to tím že ty data nejsou ukončené (céčkovskou) nulou a ten string (když mu neřekneš délku, jak poradil kolega) tak od zadané adresy projíždí paměť dokud nenarazí na nulu "někde za tím" a ty bajty navíc zahrne do svého obsahu.

Nahlásit jako SPAM
IP: 89.177.51.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 88 hostů

Podobná vlákna

Error zpráve ve verzi 2.7.12 — založil piipecek

WinSock — založil LJ1024

Winsock v WinForm — založil seldik

Winsock a NAT — založil blackman.ce

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý