JLI Spieleprogrammierung Foren-Übersicht JLI Spieleprogrammierung

 
 FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen 
 medals.php?sid=520d07149b38e20b423b60f4af3df06cMedaillen   RegistrierenRegistrieren   ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin 

sockets und unicode
Gehe zu Seite 1, 2  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 02.04.2006, 21:26    Titel: sockets und unicode Antworten mit Zitat

Hi,

ich ich möchte eine Client/Server Anwendung schreiben bei denen der client in c++ und der server in java geschrieben ist.

Um es einfach zu halten hab ich mich an die Tutorials von c-worker gehalten bei denen erstmal nur eine Zeichenkette vom Client zum Server übertragen wird.

Da Java nur Unicode benutzt habe ich das Problem das er mir immer 2 Zeichen zu einem kopiert und demnach nur Müll rauskommt.

Daher habe ich folgede Variable erstellt
CPP:
union
  {
   char buf[256];
   wchar_t wbuf[128];
  }ubuf;


und folgende Zeilen ersetzt
CPP:
// Puffer mit Daten füllen
//strcpy(ubuf.buf,"Hallo wie gehts?");
wcscpy(ubuf.wbuf, L"Hallo wie gehts?"); 

// Daten senden
//rc=send(s,ubuf.buf,strlen(ubuf.buf),0);
rc=send(s,ubuf.buf,(wcslen(ubuf.wbuf)*2),0);


das hat jetzt zur Folge das nichts mehr übertragen wird.

Hat jemand etwas ähnliches schonmal gemacht oder eine Idee wie ich unicode in ein char* packen kann ohne jedes Zeichen einzeln durchgehen zu müssen?

Grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Dragon
Super JLI'ler


Alter: 38
Anmeldedatum: 24.05.2004
Beiträge: 340
Wohnort: Sachsen
Medaillen: Keine

BeitragVerfasst am: 03.04.2006, 10:58    Titel: Antworten mit Zitat

also ich würde das so machen

CPP:
wchar_t text[] = L"Das ist eine Nachricht in UNICODE";
rc = send(socket, static_cast<char*>(text),  lstrlen(text) * sizeof(wchar_t), 0);

und beim Empfangen das gleiche
CPP:
wchar_t text[100];
rc = recv(socket, static_cast<char*>(text), 100,/*kommt hier noch was hin?*/);


Das ist jetzt nur ganz schnell aus dem Kopf gemacht wurden. Keine Garantie auf Richtigkeit.
_________________
Nur wenn man ein Ziel sieht, kann man es auch treffen.
___________
Mein Leben, Freunde und die Spieleentwicklung
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 03.04.2006, 18:37    Titel: Antworten mit Zitat

Danke schonmal für die Antwort aber leider bekomme ich mit einem static_cast einen compilerfehler

Code:

'static_cast' : 'unsigned short [34]' kann nicht in 'char *' konvertiert werden


mit einem reinterpret_cast compiliert er es aber wandelt es in char* um.
Die länge eines wchar_t* liest man mit wcslen() aus.

Bisher helfe ich mir damit aus das ich auf Javaseite beim empfangen von ASCII auf unicode convertiere und dann wieder beim Antworten zurück.

Hat jemand eine Vermutung warum das mit union nicht geklappt hat?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Dragon
Super JLI'ler


Alter: 38
Anmeldedatum: 24.05.2004
Beiträge: 340
Wohnort: Sachsen
Medaillen: Keine

BeitragVerfasst am: 03.04.2006, 19:12    Titel: Antworten mit Zitat

Chriss hat Folgendes geschrieben:
Danke schonmal für die Antwort aber leider bekomme ich mit einem static_cast einen compilerfehler

Code:

'static_cast' : 'unsigned short [34]' kann nicht in 'char *' konvertiert werden


mit einem reinterpret_cast compiliert er es aber wandelt es in char* um.
Die länge eines wchar_t* liest man mit wcslen() aus.

Bisher helfe ich mir damit aus das ich auf Javaseite beim empfangen von ASCII auf unicode convertiere und dann wieder beim Antworten zurück.

Hat jemand eine Vermutung warum das mit union nicht geklappt hat?

ich war mir nicht ganz sicher ob es vieleicht doch reinterpret_cast ist. Naja, jedenfalls sollte es jetzt funktionieren
_________________
Nur wenn man ein Ziel sieht, kann man es auch treffen.
___________
Mein Leben, Freunde und die Spieleentwicklung
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
David
Super JLI'ler


Alter: 39
Anmeldedatum: 13.10.2005
Beiträge: 315

Medaillen: Keine

BeitragVerfasst am: 03.04.2006, 20:03    Titel: Antworten mit Zitat

Hi!

Es sollt schon was übertragen werden. Allerdings wird aus L"Hallo Welt" ein:

CPP:
0x48 0x00 0x61 0x00 0x6c 0x00 ...


Schön mit nullen Terminiert. Evtl hat dein Server damit Probleme.

grüße
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 08:06    Titel: Antworten mit Zitat

Halso der reinterprete_cast macht daraus ASCII mit 1 Byte pro char.

Mit folgendem code kann ich zumindest gescheit senden
CPP:
// Puffer anlegen
void* buf = new char[256];

// Puffer fuellen
buf = (void*)L"Das ist eine Nachricht in UNICODE";

// Daten senden
rc = send(socket, ((char*)buf),  wcslen(((wchar_t*)buf)) * sizeof(wchar_t), 0);

// Puffer freigeben
delete[] buf;
buf = NULL;


Komischerweise kommt mein Server damit nicht klar. Wenn ich es als ASCII ausgebe ist es wie David das beschrieben hat. Gibt es einen unterschied zwischen wchar_t und dem UTF-16 format?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
OLiver
Super JLI'ler


Alter: 33
Anmeldedatum: 29.06.2003
Beiträge: 306
Wohnort: Jena
Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 12:00    Titel: Antworten mit Zitat

Zitat:

Halso der reinterprete_cast macht daraus ASCII mit 1 Byte pro char.


reinterprete_cast macht damit gar nix, der wandelt nur den Typ des Pointers um!
_________________
http://www.sieder25.org/ (Siedler 2 - Remake)
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 13:12    Titel: Antworten mit Zitat

OLiver hat Folgendes geschrieben:
Zitat:

Halso der reinterprete_cast macht daraus ASCII mit 1 Byte pro char.


reinterprete_cast macht damit gar nix, der wandelt nur den Typ des Pointers um!


Das ist auch das was ich gelesen habe. Aber wchar_t sollte doch eigentlich 2 Bytes pro Zeichen brauchen und wenn ich reinterprete_cast verwende sind es nur noch 1 Byte.

Koennte es sein das wchar_t nicht automatisch unicode ist?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
PeaceKiller
JLI Master


Alter: 36
Anmeldedatum: 28.11.2002
Beiträge: 970

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 13:19    Titel: Antworten mit Zitat

Reinterpret_cast ist in dieser hinsicht einfach nur dumm. Aber mit ein paar geschickten Byteshifts sollte es eigentlich möglich sein UCS-2 auf zwei Bytes aufzuteilen.

edit: Ist natürlich Quatsch was hier steht. einfach mit memcopy die bytes rumkpieren.
_________________
»If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.«
– Robert X. Cringely, InfoWorld magazine


Zuletzt bearbeitet von PeaceKiller am 04.04.2006, 21:38, insgesamt einmal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
GreveN
JLI Master


Alter: 38
Anmeldedatum: 08.01.2004
Beiträge: 901
Wohnort: Sachsen - Dresden
Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 16:10    Titel: Antworten mit Zitat

Noch dazu ist 'reinterpret_cast' implementierungsabhängig und sollte daher vermieden werden.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Yahoo Messenger MSN Messenger
Dragon
Super JLI'ler


Alter: 38
Anmeldedatum: 24.05.2004
Beiträge: 340
Wohnort: Sachsen
Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 17:47    Titel: Antworten mit Zitat

Chriss hat Folgendes geschrieben:
Halso der reinterprete_cast macht daraus ASCII mit 1 Byte pro char.

Mit folgendem code kann ich zumindest gescheit senden
CPP:
// Puffer anlegen
void* buf = new char[256];

// Puffer fuellen
buf = (void*)L"Das ist eine Nachricht in UNICODE";

// Daten senden
rc = send(socket, ((char*)buf),  wcslen(((wchar_t*)buf)) * sizeof(wchar_t), 0);

// Puffer freigeben
delete[] buf;
buf = NULL;


Komischerweise kommt mein Server damit nicht klar. Wenn ich es als ASCII ausgebe ist es wie David das beschrieben hat. Gibt es einen unterschied zwischen wchar_t und dem UTF-16 format?


Ganz ehrlich, ich spiel jetzt mal Patrick, es geht nicht anders. Weißt du überhaupt was du da machst? Das ist der größte Schwachsinn den ich je gesehen haben.

CPP:
// Puffer fuellen
buf = (void*)L"Das ist eine Nachricht in UNICODE";

Schon mal was von memcpy oder strcpy gehört? Sicherlich nicht. Warum der sinnlose cast? Warum überhaupt vorher das anlegen des Speicherbereichs? Soll ich heulen oder lachen? Mad

CPP:
// Puffer anlegen
wchar_t buf[1024]

// Puffer fuellen
lstrcpy(buf, L"Das ist eine Nachricht in UNICODE");

// Daten senden
rc = send(socket, reinterpret_cast<char*>(buf),  wcslen(buf) * sizeof(wchar_t), 0);

// Puffer freigeben


BTW: wenn du in der Konsole UNICODE verwenden willst, dann kann du auch wcout nutzen.

Kommentar von Patrick (der ja sinnlos gebannt wurde)
Zitat:

Patrick (07:34 PM) :
du kannst doch keinen pointeradresse casten und dann darauf zuweisen um einen anderen Zeichensatz zu bekommen
Patrick (07:34 PM) :
sag dem schnell er soll aufhören leute zu verblöden
Patrick (07:36 PM) :
boah ne der thread ist ja ein witz


Ich will nicht diskutieren, ich hab alles gesagt, ich werd auch hierzu nichts mehr schreiben.Ich weiß die Nachricht ist hart, aber es muss eben auch mal hart sein.
_________________
Nur wenn man ein Ziel sieht, kann man es auch treffen.
___________
Mein Leben, Freunde und die Spieleentwicklung
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 18:22    Titel: Antworten mit Zitat

Zitat:

Weißt du überhaupt was du da machst?

Nein sowohl wchar_t als auch reinterpreter_cast sind für mich neu.

Zitat:

Warum überhaupt vorher das anlegen des Speicherbereichs?


Das ist die Maximalgröße des puffers den ich über das Netzwerk schicken will. Ich hab mich hier an das Beispiel von c-worker gehalten.

Zitat:

wenn du in der Konsole UNICODE verwenden willst, dann kann du auch wcout nutzen.

Ich will es an einen server schicken der in java geschrieben ist.

Zitat:

Ich will nicht diskutieren, ich hab alles gesagt, ich werd auch hierzu nichts mehr schreiben.Ich weiß die Nachricht ist hart, aber es muss eben auch mal hart sein.

Ich hab kein Problem damit wenn man mir etwas direkt sagt, aber Zitiate wie dieser
Zitat:

boah ne der thread ist ja ein witz

helfen mir nicht umbedingt dabei das Problem zu erkennen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
abc_d
JLI Master Trainee


Alter: 34
Anmeldedatum: 27.01.2003
Beiträge: 615

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 19:33    Titel: Antworten mit Zitat

@Dragon ist es eigentlich absicht das du am Schluss vom String den du sendest den String nicht mit 0 terminierst? Wenn ich strings verschicke mache ich das gerne.

Ausserdem stress bitte nicht so.
_________________
http://mitglied.lycos.de/sarti/linuxisevil.gif Linux is evil - get the fact.

Never touch a running System - der Systemling
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Dragon
Super JLI'ler


Alter: 38
Anmeldedatum: 24.05.2004
Beiträge: 340
Wohnort: Sachsen
Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 19:48    Titel: Antworten mit Zitat

BlackLordOfDragons hat Folgendes geschrieben:
@Dragon ist es eigentlich absicht das du am Schluss vom String den du sendest den String nicht mit 0 terminierst? Wenn ich strings verschicke mache ich das gerne.

Ja es ist Absicht. Der Compiler macht das Automatisch. Wenn er es nicht machen würde, dann könnte man sowas gar nicht machen:
CPP:
std::wcout << L"Nullterminiert oder nicht?" std::endl;


@Chris:
ich glaube ich habe etwas überreagiert, da ich mit der gesamten Situation im Forum nicht zu frieden bin. Hier werden leute einfach ohne Grund gebant und Threads, die sich mit dem Thema beschäftigen und die zu klärung helfen könnten, einfach geschlossen.

Zurück zu deinem Problem. Das Problem ist, ich kann mir dein Problem nicht vorstellen. Was macht der Server und unterstütz er überhaupt UNICODE? Eigentlich sollte es so wie ich es in meinem unfreundlichem Beitrag geschrieben habe funktionieren.

Zitat:
Nein sowohl wchar_t als auch reinterpreter_cast sind für mich neu.

Kein Problem. wchar_t beitet speicherplatz für 16 bit und wird üblicherweise für UNICODE verwendet. Der reinterpret_cast konvertiert nicht, sondern sagt nur "tue so als wärst du was anderes".

Zitat:
Das ist die Maximalgröße des puffers den ich über das Netzwerk schicken will. Ich hab mich hier an das Beispiel von c-worker gehalten.

Naja, es reicht eigentlich wenn du ein normales Feld nimmst, so wie in meinem beispiel.

wchar_t text[MAX_SIZE] = L"blabla";

Zitat:
Ich will es an einen server schicken der in java geschrieben ist.

Aso, unterstützt der Server UNICODE?

Zitat:
ich hab kein Problem damit wenn man mir etwas direkt sagt, aber Zitiate wie dieser helfen mir nicht umbedingt dabei das Problem zu erkennen.

das liegt aber daran, das viele beiträge hier einfach quatsch und falsch sind. Außerdem wurden Lösungen nicht ernst genommen und später wird rumgemault, dass doch etwas nicht geht, obwohl schon alles gesagt wurde.
_________________
Nur wenn man ein Ziel sieht, kann man es auch treffen.
___________
Mein Leben, Freunde und die Spieleentwicklung
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Chriss
Senior JLI'ler



Anmeldedatum: 18.08.2004
Beiträge: 267

Medaillen: Keine

BeitragVerfasst am: 04.04.2006, 20:50    Titel: Antworten mit Zitat

@Dragon
Ist vergessen Wink

Zitat:

Zitat:
Ich will es an einen server schicken der in java geschrieben ist.

Aso, unterstützt der Server UNICODE?

Laut dem open Book "Java ist auch nur eine Insel" benutzt Java bei Strings immer UNICODE. Wenn ich etwas empfange sind es erstmal bytes und ich erzeugen dann daraus einen String und gebe explizit an das er das Format UTF-16 verwenden soll.

Es handelt sich bei den Programmen nur um kleine Beispiele an denen ich die Technik dahinter verstehen will.

Server
Code:

import java.net.*;
import java.io.*;

public class server
{
  public static void main( String args[] ) throws IOException
  {
    ServerSocket server = new ServerSocket( 12345 );

   
     System.out.println("Warte auf client...");
      Socket client = server.accept();

      BufferedInputStream in = new BufferedInputStream( client.getInputStream());
      System.out.println("Lese...");
      byte[] input = new byte[256];
      int available = 0;
      try
      {
         available = in.read(input);
      }
      catch(SocketException ex)
      {
         System.out.println(ex.toString());
      }
     
      if(available>0)
         System.out.println(new String(input, "UTF-16").subSequence(0,available));
   
     System.out.println("close...");
     client.close();
   
    server.close();
  }
}



Client
CPP:
// sockclient.cpp

#include <windows.h>
#include <string>
#include <stdio.h>

//Prototypen
int startWinsock(void);

int main()
{

  // Variablen
  long rc;
  SOCKET s;
  SOCKADDR_IN addr;

  // Starte Winsock und speichert den Rückgabewert
  rc=startWinsock();

  // Erfolgsprüfung
  if(rc!=0)
  {
   // Fehlerausgabe
    printf("Fehler: startWinsock, fehler code: %d\n",rc);
   // Programm beenden
    return 1;
  }
  else // Alles erfolgreich
  {
   // Erfolgsausgabe
    printf("Winsock gestartet!\n");
  }
  // Socket erstellen (internet,TCP/IP,kein Protokoll oder standard)
  s=socket(AF_INET,SOCK_STREAM,0);

 // Erfolgsprüfung
if(s==INVALID_SOCKET)
{
  // Fehlerausgabe
  printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
  // programm beenden
  return 1;
}
else // Alles hat funktioiniert
{
  // Erfolgsausgabe
  printf("Socket erstellt!\n");
}
// zuerst alles auf 0 setzten
memset(&addr,0,sizeof(SOCKADDR_IN));
// Internetprotokol wählen
addr.sin_family=AF_INET;
// wir verwenden mal port 12345 (durch htons() umgewandelt)
addr.sin_port=htons(12345);
// zielrechner ist unser eigener
addr.sin_addr.s_addr=inet_addr("127.0.0.1");

// Verbindung aufbauen und rückgabewert speichern
rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR));
// auf Fehler prüfen
if(rc==SOCKET_ERROR)
{
  // Fehler ausgeben
  printf("Fehler: connect gescheitert, fehler code: %d\n",WSAGetLastError());
  // Programm beenden
  return 1;
}
else // erfolgreich verbunden
{
  // Erfolgsmeldung
  printf("Verbunden mit 127.0.0.1..\n");
}

// Daten senden
void* buf2 = new char[256];
buf2 = (void*)L"Das ist eine Nachricht in UNICODE";
rc = send(s, ((char*)buf2),  wcslen(((wchar_t*)buf2)) * sizeof(wchar_t), 0);
delete[] buf2;
buf2 = NULL;

  // Programm erfolgreich beenden
  return 0;
}

// Funktion zum Starten von Winsock
int startWinsock(void)

{
  // benötigte Struktur
  WSADATA wsa;
  // Winsock starten und Status zurückgeben
  return WSAStartup(MAKEWORD(2,0),&wsa);
}



Der entscheidende Block ist
CPP:
// Daten senden
void* buf2 = new char[256];
buf2 = (void*)L"Das ist eine Nachricht in UNICODE";
rc = send(s, ((char*)buf2),  wcslen(((wchar_t*)buf2)) * sizeof(wchar_t), 0);
delete[] buf2;
buf2 = NULL;


Wenn sich jetzt jemand denkt "So ein scheiß der benutzt C und die alten header..." Es ist das beispiel von c-worker und wenn ich verstanden habe wie es geht schreib ich mir eine vernünftige C++ Klasse.

Der client macht soweit alles richtig und sendet die Daten im Format

"D 0x00 a 0x00 s 0x00" ....

Beim server lese ich dann nur ????????????????????????? gefolgt von kästchen. Tausche ich beim Server UTF-16 gegen UTF-8 bekomm ich alle Buchstaben wobei jedem Buchstabe ein 0x00 folgt.

Momentan vermute ich das UTF-16 wie es Java benutzt nicht mit dem wchar_t meines alten VC++ 6.0 Compilers kompatiebel ist.

Stelle ich bei beiden auf UTF-8 bzw char* um kommen alle Zeichen richtig an.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    JLI Spieleprogrammierung Foren-Übersicht -> Entwicklung Alle Zeiten sind GMT
Gehe zu Seite 1, 2  Weiter
Seite 1 von 2

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.


Powered by phpBB © 2001, 2005 phpBB Group
Deutsche Übersetzung von phpBB.de

Impressum