Forum: PC-Programmierung Datenübertragung über TCP Socket von c auf java


von BUBU (Gast)


Lesenswert?

Hallo!
ich versuche schon seit geraumer zeit einen TCP/IP socket in c zu 
erstellen der einfach einen unsigned char mit write wegsendet und dieser 
dann mit einem java client empfangen wird.
Das funktioniert auch alles sehr gut bis auf wenn ich einen unsigned 
char größer 127 wegsenden will kommt mir immer auf der java seite die 
Zahl 253 heraus. also für alle werte größer 7 bit ein konstanter wert :(

der c seitige code:
1
unsigned char g_valid_message[LENGTH_BIG_PACKET];
2
3
4
void inittcpsocket()
5
{
6
     struct sockaddr_in serv_addr;
7
8
     sock = socket(AF_INET, SOCK_RAW, 0);
9
     if (sock < 0) 
10
        BailOut("SOCKET: Opening socket error!");
11
     
12
     bzero((char *) &serv_addr, sizeof(serv_addr));
13
14
     serv_addr.sin_family = AF_INET;
15
     serv_addr.sin_addr.s_addr = INADDR_ANY;
16
     serv_addr.sin_port = htons(g_port);
17
     
18
     if (bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
19
       BailOut("SOCKET: binding error! Maybe the port is used by an other application!");
20
       
21
     fprintf(stderr,"TCP-Socket configured! Program is listening on port = %d \n", g_port);
22
}
23
24
void *sendwithtcpsocket( void *arg )
25
{
26
  int clilen, newsockfd,n,i,length;
27
  struct sockaddr_in cli_addr;
28
  unsigned char recvbuf[2];
29
  
30
  listen(sock,5);
31
    clilen = sizeof(cli_addr);
32
  
33
  while (TRUE) 
34
  {
35
       newsockfd = accept(sock, (struct sockaddr *) &cli_addr, &clilen);
36
       if (newsockfd < 0) 
37
          BailOut("ERROR on accept");
38
       
39
       while(TRUE)
40
       {
41
         bzero(recvbuf,2);
42
         n = read(newsockfd,recvbuf,255);
43
         if (n < 0) 
44
         {
45
           fprintf(stderr,"ERROR reading from socket");
46
           break;
47
         }
48
         
49
         printf("Here is the message: %d %d\n",recvbuf[0],recvbuf[1]);
50
         if(recvbuf[0]==0)  /* end condition */
51
           break;
52
         
53
         if(g_bigreceived==TRUE)  /* get size of package */
54
      {
55
        length=LENGTH_BIG_PACKET;
56
        g_bigreceived=FALSE;
57
      }
58
      else
59
        length=LENGTH_SMALL_PACKET;
60
         
61
         n = write(newsockfd,g_valid_message,length);
62
         if (n < 0) 
63
         {
64
           fprintf(stderr,"ERROR writing to socket");
65
           break;
66
         }
67
       }
68
     } /* end of while */
69
}

der java seitige teil
1
public class TcpConnection {  
2
  private int length = 0;
3
  
4
  private Socket socket = null;
5
  private PrintWriter out = null;
6
    private BufferedReader in = null;
7
  
8
  public TcpConnection(String host, int port)
9
  {    
10
    try {
11
      socket = new Socket();  
12
      socket.connect(new InetSocketAddress(host, port));
13
      
14
      out = new PrintWriter(socket.getOutputStream(), true);
15
            in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
16
      
17
      socket.setSoTimeout(2000);
18
      
19
    } catch (IOException e) {
20
      e.printStackTrace();
21
      System.err.println("Socket creating ERROR: " + e.getMessage());
22
    }
23
  }
24
  
25
  public short[] receiveData()
26
  {
27
    byte number = 0;
28
    short[] result = receiveData(number);
29
    
30
    return result;
31
  }
32
  
33
  public short[] receiveData(byte number)
34
  {
35
    char[] buffer = new char[210];
36
    
37
    try {
38
      //write welcome message
39
      out.println(number);
40
      
41
      //get response
42
      length = in.read(buffer);
43
44
    } catch (IOException e) {
45
      System.err.println("ERROR reading from TCP-Socket: " + e.getMessage());
46
    }
47
    
48
    short[] data = unsignedconverter(buffer);
49
       
50
      return data;
51
  }
52
  
53
  /**
54
   * returns the length of the current packet
55
   * @return
56
   */
57
  public int getLength()
58
  {  
59
    return length;
60
  }
61
  
62
  public void closeConnection()
63
  {
64
    if(socket != null)
65
    {
66
      try {
67
        socket.close();
68
      } catch (IOException e) {
69
        System.err.println("ERROR closing TCP-Socket: " + e.getMessage());
70
      }
71
    }
72
  }
73
  
74
    /**
75
     * Converts a char array into a unsinged short array
76
     * @param input
77
     * @return
78
     */
79
    private short[] unsignedconverter(char[] input)
80
    {
81
      short[] result = new short[input.length];
82
83
        int firstByte = 0;
84
    
85
        for(int i=0; i<input.length;i++)
86
        {
87
          firstByte = (0x000000FF & ((int)input[i]));
88
          result[i] = (short)firstByte;
89
        }
90
        
91
      
92
      return result;
93
    }

ich glaube eher das der fehler sich irgendwo auf der c seite befindet... 
kann ja sein das ein normales write() hier den unsigned char in einen 
singed umwandelt... jedoch wäre das dann nicht die erklärung für den 
immer konstanten wert von 253

bitte um hilfe danke :)

von Stefan S. (dangermouse)


Lesenswert?

Hallo!

Derzeit habe ich ein ähnliches Projekt vor mir. Ich schreibe einen 
SocketServer in Java und muss mit C-Clients umgehen können.

Im "Java Kochbuch" von O'Reilly befindet sich ein hinweis, dass man auf 
C-Seite Network-Byte-Order-Macros verwenden sollte. Zur Datenübertragung 
gibt es da wohl Makros in den Internet Header Dateien oder in 
<machine/endian.h>

Auf Java-Seite lässt sich das ganze dann mittels DataInputStream lesen.
Als Beispiel hat der Autor eine C-Implementierung angegeben, die die 
entsprechenden Makros verwendet und eine Datei mit zufälligen Werten 
füllt. Der Code kann aber auch für Netzwerksockets verwendet werden.

http://javacook.darwinsys.com/javasrc/io/WriteRandom.c

Viele Grüße

Stefan

von Markus V. (Gast)


Lesenswert?

Sagt mal, hat hier irgend eine (Schul-)Klasse dies als Hausaufgabe 
bekommen?? Es sind jetzt schon deren drei...

@BUBU
schau doch mal unter Beitrag "Daten per C++ an Java-Programm: Java-Typenproblem?" ( Daten 
per C++ an Java-Programm: Java-Typenproblem? )

Grüße
Markus V.

von Johannes S. (johanness)


Lesenswert?

Es ist zwar schon ne Weile her, dass ich in Java Netzwerkprogramme 
geschrieben habe (und selbst da ging nur Klartext übers Netz), aber sind 
Reader/Writer wirklich sinnvoll? Wenn ich mich recht entsinne waren die 
eher für Klartext denn für Binärdaten gedacht. Wie gesagt, schon ewig 
her, bin ein wenig aus der Übung...

von Maik R. (kiamur)


Lesenswert?

Hallo!

Ich bin mir nicht sicher, ob meine Antwort dir weiterhelfen wird, aber 
es könnte daran liegen, dass Java einfach keine 'unsigned' Typen kennt. 
Möchte man dennoch unsigned Typen verwenden, so kann man sich ja mal 
diesen Workaround anschauen, der mir bei der Problematik auch schon mal 
die Augen geöffnet hat: 
>http://darksleep.com/player/JavaAndUnsignedTypes.html <.

Wie gesagt, ich weiß nicht so recht, ob ich dein Problem überhaupt 
richtig verstanden habe, aber dieses 'unsigned'-Problem bei Java hat 
mich halt aufhorchen lassen.

Gruß
Maik

von Johannes S. (johanness)


Lesenswert?

Habs noch mal nachgelesen, Reader/Writer ist wirklich für Texte gedacht, 
darum auch beim BufferedWriter das newLine(), das immer den für die 
Plattform richtigen Zeilenvorschub generiert :)

Wenn man ein Problem mit signed/unsigned hat, dann bekommt man im 
Fehlerfall eine Differenz zwischen richtigem und falschem Wert, die 
einer Zweierpotenz entspricht (2^8, 2^16, 2^32 oder 2^64, je nach Länge 
des Integers), Stichwort "Zweierkomplement". Der beschriebene Fehler 
(mehrere Zeichen werden auf eine bestimmte Zahl abgebildet) sieht eher 
so aus, als habe der Reader versucht, die Zeichen als Text zu 
interpretieren und verschiedene Zeichen als "unbekannt" gelesen 
(vielleicht weil sie nicht im 7-bit-Standard-ASCII drin sind). Habe 
leider gerade kein JDK hier installiert, um das schnell zu testen...

Wäre schön, wenn BUBU mal schreiben könnte, obs inzwischen läuft, was 
ihm dabei geholfen hat, und falls es nicht läuft, wie das Problem 
inzwischen aussieht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.