sockets send() übterträgt Zahlen nicht richtig

Jennesta

Erfahrenes Mitglied
Hi,
ich musste kurzfristig ein Projekt übernehmen und hatte daher leider nicht genug Zeit mich umfassend mit Sockets auseinander zusetzen.
Mein Problem ist folgendes. Ich habe eine Matrix, die größtenteils aus Nullen besteht (Größe 16x16). Ich lese diese Matrix in ein char Array ein und übertrage dieses, bis zu einer vorher ausgrechneten Stelle, ab der nur noch Nullen kommen.

Nun habe ich das senden noch nicht mit den Matrizen ausprobiert, sondern mit kleineren Versuchs Programmen. Mein Problem ist vorallem, dass wenn ich eine 0 im array habe, dass irgendetwas an der Übertragung schief läuft. Ich vermute es liegt irgendwie auch am ASCII-Zeichen für 0. Aber wie übertrage ich denn ein Array voller Zahlen, wenn die send()-Fkt nur char-Arrays annimmt.

Falls sich einer auch den Quelltext ansehen möchte stelle ich diesen mal rein. Vielleicht liegt es auch an einem anderen Punkt.

main die sendet:
C++:
int main(int argc, char* argv[]) {
	SocketCon SockCon;
	SockCon.initialisiereSenden();
	char stream[100] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
	stream[0] = 0;
	stream[1] = 26;
	SockCon.sockSend(stream);
	system("pause");
	return 0;
}

dieheader-datei für meine Socket-fkt
C++:
#include "socketcon.h"

SocketCon::SocketCon() {}
SocketCon::~SocketCon() {}

void SocketCon::initialisiereEmpfang() {
	
	printf("Bitte Port angeben: ");
    scanf("%d",&port);

	// Mit WSAStartup werden die Sockets initialisiert
	result = WSAStartup(MAKEWORD(2, 0), &wsa);
	if(result != 0)
	{
		printf("Fehler bei WSAStartup(): Code %d", result);
	}
	// Initialisieren der Struktur SOCKADDR_IN
    memset(&addrBind, 0, sizeof(SOCKADDR_IN));
    addrBind.sin_port      = htons(port);
    addrBind.sin_family       = PF_INET;
    addrBind.sin_addr.s_addr = ADDR_ANY;

	// Initialisierung des socketAccept
    socketAccept = socket(PF_INET, SOCK_STREAM, 0);
    result=bind(socketAccept, (SOCKADDR*) &addrBind, sizeof(SOCKADDR_IN));
    if(result == SOCKET_ERROR)
    {
        printf("Fehler in bind(): Code %d", WSAGetLastError());
    }

	// socketAccept geht in den "listen-mode"
    result = listen(socketAccept, 10);
	if(result == SOCKET_ERROR)
    {
        printf("Fehler in listen(): Code %d", WSAGetLastError());
    }
}

void SocketCon::initialisiereSenden() {
	printf("Bitte IP-Addresse des Empfängers eingeben: ");
	cin >> ip;
	printf("Bitte Port angeben an den gesendet wird: ");
    scanf("%d",&port);
}

void SocketCon::sockSend(char *streamArray) {
    result = WSAStartup(MAKEWORD(2, 0), &wsa);
    if(result != 0) {
        printf("Fehler bei WSAStartup(): Code %d", result);
    } else {
        printf("WSAStartup() erfolgreich!");
    }
    sock = socket(AF_INET, SOCK_STREAM, 0);

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(ip);
    addr.sin_port = htons(port);

    connect_ret = connect(sock, (sockaddr *)&addr, sizeof(addr));
	
	int length = static_cast<int>(streamArray[0])*100 + static_cast<int>(streamArray[1]);
	printf("%d-%d-%d",streamArray[0], streamArray[1], length);
    bytes = send(sock, streamArray, length, 0);
    if (bytes == -1) {
        perror("send() fehlgeschlagen");
    } else {
        printf("\nAlles ok\n");
		printf("Es wurde : \"%s\" übertragen",streamArray);
    }
    closesocket(sock);
}

void SocketCon::receive(char* streamArray) {
    // accept() blockiert solang, bis eine Verbindung angenommen wurde
    socketConnect = accept(socketAccept, NULL, NULL);   
    if(socketConnect == SOCKET_ERROR) {
        printf("Fehler in accept(): Code %dProgramm wird fortgesetzt",
        WSAGetLastError());
		//continue;
    }
    
	memset (buf,0,264);
	SOCKET socket = socketConnect;  // der Parameter wird derefernziert
	int bytes;

	bytes = recv(socket, streamArray, sizeof(streamArray) - 1,0);
	if (bytes == -1) {
		printf("blub - recv() in \"Thread()\" fehlgeschlagen %d", WSAGetLastError());
	}

	printf("Server: %s-%d-%d\n", streamArray, streamArray[0], streamArray[1]);

	// Verbindung schliesen
	closesocket(socket);
}
und falls interessant die header-Datei die empfängt:
C++:
#include "../socketcon.h"
#include <iostream>

int main(int argc, char* argv[]){
	SocketCon SockCon;
	char streamArray[256+8];
	SockCon.initialisiereEmpfang();
	SockCon.receive(streamArray);

	int i = 0;
	printf("\nmain : %d\n", (static_cast<int>(streamArray[0])*100+static_cast<int>(streamArray[1])));
	while((static_cast<int>(streamArray[0])*100+static_cast<int>(streamArray[1])) > i) {
		printf("\n->%c", static_cast<char>(streamArray[i]));
		i++;
	}
	//std::cout << streamArray << endl;

	system("pause");
	return 0;
}

Dazu sei gesagt die Stelle an der die letzte relevante Zahl steht berechnet sich zu stelle = streamArray[0]*100+streamArray[1]. Auch funktioniert das Übertragen von festen char Arrays wie zb "Hallo" wunderbar. Es muss irgendwie an den Zahlen liegen.

Wäre für eine hilfreiche Antwort super dankbar.

Grüße Jennesta
 
Hallo,

zwei Sachen, die mir beim Überfliegen aufgefallen sind:
C++:
bytes = recv(socket, streamArray, sizeof(streamArray) - 1,0);
Damit liest du immer maximal 3 bzw. 7 Bytes ein, da du mit sizeof(streamArray) die Größe eines Zeigers ermittelst. Die ist i.d.R. auf 32-Bit-Systemen 4 Bytes und auf 64-Bit-Systemen 8 Bytes. Übergib der Methode besser die Größe des reservierten Speichers als Parameter und verwende den.

C++:
printf("Server: %s-%d-%d\n", streamArray, streamArray[0], streamArray[1]);
streamArray wird mit dem Formatspezifizierer %s nur bis zum ersten '\0' ausgegeben. Es können also durchaus mehr Zeichen übertragen worden sein, als bei dieser Ausgabe sichtbar sind.

Wenn du allgemein beliebige Datentypen übertragen willst, geht das in etwa so:
C++:
// Senden
float data[100];
send(sock, reinterpret_cast<char *>(data), 100*sizeof(float), 0);

// Empfangen
float data[100];
recv(sock, reinterpret_cast<char *>(data), 100*sizeof(float), 0);
Evtl. musst du noch auf die Bytereihenfolge achten.

Grüße,
Matthias
 
Zuletzt bearbeitet:
Wenn du auf diese Weise Binärdaten versendest, gehst du davon aus, dass Sender und Empfänger dieselbe interne Darstellung für die entsprechenden Datentypen verwenden. Das muss aber z.B. wegen unterschiedlicher Byte-Reihenfolge nicht unbedingt gegeben sein. Da müsstest du dann ggf. Umwandlungen vornehmen.

Grüße,
Matthias
 
Coole Sache. Ich denke es klappt nun habe deine Änderungen auch noch etwas modifiziert zu:
C++:
bytes = send(sock, reinterpret_cast<char *>(streamArray), 100*sizeof(int), 0);

streamArray ist nun auch kein char Array mehr, sondern int und das passt dann auch besser in das ganze Konzept. Morgen versuche ichs noch ins Projekt reinzuhaun. Hoffe das klappt. Vielen Dank.
 
Coole Sache. Ich denke es klappt nun habe deine Änderungen auch noch etwas modifiziert zu:
C++:
bytes = send(sock, reinterpret_cast<char *>(streamArray), 100*sizeof(int), 0);
reinterpret_cast ist hier natürlich richtig, danke für den Hinweis. Ich erlaube mir mal, meinen früheren Beitrag mit dem falschen static_cast zu korrigieren.

Grüße,
Matthias
 
Zurück