Vollständige Version anzeigen : [C/C++] C Server + Java Client [Einführung - Socketprogrammierung]


schiene
07.12.2006, 23:52

[ Eine kleine Einführung in die Socketprogrammierung ]
- man sollte schon einigermaßen in C und Java geübt sein, aber auch für Anfänger hoffentlich verständlich, aber sicherlich nicht leicht durchschaubar :) -

Was beinhaltet dieses kleine Tutorial

Server in C (Linux) - Der Daten sendet
Client in Java - Der Daten anfordert


und das ganze mit Sockets mit TCP Verbindung (mit IPv4)

Bemerkung:
Die Socketprogrammierung ist eine sehr komplexe Angelegenheit und ich kann in diesem Tut sicherlich nicht auf jede Einzelheit eingehen, dennoch möchte ich einfach mal mein wissen weitergeben. Als ich mit programmieren angefangen habe hat mich dieses Thema am meisten gelockt weil es einfach schön ist, wenn ein Server und ein Client gut zusammenarbeiten :)
Aber warum ein Server in C und ein Client in Java? Nun ja man kann sicherlich auch den Client C schreiben, dennoch denke ich mir das Folgendermaßen: C ist sehr viel schneller als Java und eignet sich deshalb gut als Server für einen kleinen Linuxserver. Der Javaclient ist dagegen langsamer gut, aber er ist plattformunabhängig und damit sowohl in Linux einsetzbar als auch in Windows, als auch bei anderen Betriebssystemen die Java untersützen. C ist im Grunde auch plattformunabhängig allerdings haben Linuxsysteme andere Header-Dateien für Sockets als Windows, das mit Winsocks arbeitet.

[ Server ]
Zunäachst brauchen wir einen Server der eine Verbindung annimmt, dem Client die Daten zusendet und dann die VErbindung zwischen ihm und dem client schließ und auf die nächsten Clients wartet.
Im Model sieht dies so aus:

[Server Socket erzeugen] - socket()
[Adresse und Portnummer festlegen] - bind()
[Server starten - horchen lassen] - listen()

(Routine, um Verbindungen anzunehmen und zu bearbeiten)
[eine Verbindung annehmen
und einen neuen Socket erzeugen] - accept()
[Daten senden..;] - write()
[Verbindung schließen] - close()


Zunächst einfach mal den Code auf sich wirken lassen :tongue:, ich hoffe die Erklärungen sind eindeutig

//File server;c
#include <sys/types;h> // für Datentypen
#include <sys/socket;h> // für Socket-Funktionen
#include <stdio;h> // für allgemeine Ein/Ausgabe
#include <netinet/in;h> //für IP-Adresse
#include <arpa/inet;h> // für die Socket-Datenstruckturen
#include <string;h> // für Stringfunktionen

main(){
int server_socket, neuer_socket; // um Server - / Clientinformationen zu speichern
int anzahl, laenge; // [anzahl] die Anzhal der empfangenen Zeichen,[laenge] die Laenge/Größe der Server- / Clientinformationen, diese brauchen wir später als Parameter
char empfangen[1000]; // Buffer für empfangene Zeichen
char senden[1000]; //Buffer für gesendete Zeichen

int verbindung_nummer = 1; // ein Counter für die Anzahl der Verbindungen

struct sockaddr_in serverinfo, clientinfo; //structuren für Server / Client - in diesen werden Port, Ip-Adresse Art der Verbindung gespeichert
unsigned short int portnummer = 7777; //unser Port an dem der Server horchen soll
char ip_adresse[] = "127;0;0;1"; // Die IP-Adresse an die der Server "gebunden" wird

printf("\n Server socket()..;");

/*
Wir erstellen einen neuen Socket und zwar mit den Parametern:
AF_INET, d;h. wir benutzen die Transportprotokolle des Internets, also IP und TCP oder UDP
SOCK_STREAM, d;h. wir benutzen das TCP Protokoll
0 hier kan man nochmal einen speziellen Typ eines Transportprotokolls auszuwählen, was in unserem Beispiel aber nicht nötig ist, denn wir haben mit den vorherigen Parametern schon klar gemacht, was für einen Socket wir haben wollen
*/
server_socket = socket(AF_INET, SOCK_STREAM, 0);

// die Serverstruktur mit Daten füllen
serverinfo;sin_family = AF_INET; //Family setzen
serverinfo;sin_addr;s_addr = inet_addr(ip_adresse); //ip-adresse setzen, dabei inet_addr verwenden, um die Zeichenkette in eine 32-Bit-Zahl umzuwandeln, man kann hier auch die Konstante INADDR_ANY setzen, um dem Socket zu sagen, dass er an allen IP Adressen horchen soll
serverinfo;sin_port = htons(portnummer); // Port setzen, dabei htons() verwenden, um auch den Port in BIts umzuwandeln
laenge = sizeof(serverinfo); // wir müssen die länge der Struktur speichern, dabei wir diese noch als Parameter benötigen
/*
wer sich mehr für Ip-Adressen und dessen Umwandlung in Bits ineteressiert und warum dies nötig ist. schaut mal Wikipedia vorbei:
;de;wikipedia~org/wiki/IPv4
*/

printf("\n Server: bind()..;");

/*
Den Server an seinen Port und IP binden.
wir brauchen einmal den erstellten Socket also server_socket
und wir brauchen die Struktur allerdings, benötigt bind möglicherweise nicht sockaddr_in sondern nur sockaddr , deswegen müssen wir die serverinfo mittel Zeiger und Refenz in sockaddr umwandeln
der Parameter ist die laenge der Struktur
*/
bind(server_socket, (struct sockaddr *)&serverinfo, laenge);

printf("\n Server: listen()..;\n Server mit IP %s an Port %d wartet..;", ip_adresse, portnummer);

/*
fange an zu horchen
die 3 gibt hierbei an, wie lang die Warteschlange für den Socket ist, d;h. es können 3 Clients gleichzeitig einen Verbindungswunsch schicken, dadurch wird der Server selber etwas entlastet. Natürlich kann man den Wert auch höher stellen, nur das jeweilige Betriebsystem nimmt eine zu große Warteschlange nicht als akzeptabel an und verringert sie bis zur Obergrenze
*/
listen(server_socket, 3);

// Endlosschleife um Clients zu akzeptieren
while (1){
printf("\n Verbindung %d wartet..;", verbindung_nummer);

/*
neue Clients akzeptieren und dabei die Clientstruktur setzen, deswegen ist clientinfo als Referenz und die länge auch
*/
neuer_socket = accept(server_socket, (struct sockaddr *)&clientinfo, &laenge);

printf("\n Verbindung mit %s \n", inet_ntoa(clientinfo;sin_addr));

/* Daten die man empfängt in die Variable empfangen schreiben, man muss hier als letzten Parameter einen Puffer angeben, wie viele Daten empfangen werden können, ist der Puffer zu klein, können möglicherweise nicht alle Daten erfasst werden, man könnte dann eine weitere Schleife einbauen
*/
anzahl = read(neuer_socket, &empfangen, sizeof(empfangen));
// Man muss am Ende der Daten eine 0 setzen, damit erkannt wird wo die Nachricht endet, sonst hat man den "Datenmüll" mit dem man nichts anfangen kann noch in seinen Empfangen Daten, um zu sehen wie dies aussieht, könnt ihr ja mal diesen Schritt weglassen
empfangen[anzahl] = 0;

printf("\n\n Empfangen : \n\n%s", empfangen);

/*
Was wurde empfangen?
*/
if (strstr(empfangen, "Hi") != NULL){
strcpy(senden, "du");
// Wenn der Client "Hi" sagt, dann kopieren wir "du" in die Variable senden, und senden diese Daten, dabei muss auch die laenge von senden als letzter Parameter übergeben werden. Das gleiche Spiel bei den anderen Überprüfungen, und wenn kein Befehl gepasst hat, ist der Befehl unbekannt
write(neuer_socket, senden, strlen(senden));
}else if(strstr(empfangen, "Wie geht's?") != NULL){
strcpy(senden, "gut");
write(neuer_socket, senden, strlen(senden));
}else{
strcpy(senden, "unbekannter befehl");
write(neuer_socket, senden, strlen(senden));
}

// wir schließen den Socket, um neue Verbindungen aufnehmen zu können
close(neuer_socket);
printf("\n");
verbindung_nummer++;
}

// Wir schließen den Server Socket, allerdings wird diese Stellen niemals erreicht, da wir eine Endlosschleife zuvor eingebaut haben
printf("Beenden\n\n");
close(server_socket);

return(0);
}


das ganze dann mit "gcc -o server server;c" kompilieren und ausführen.

Dieser Server ist sehr Simpel gehalten. Man kann ihn verbessern, besonders mit Threads. Dann hat man einen Thread der auf Clients wartet und wenn ein Client sich verbunden hat, öffnet er einen neuen Thread, um Operationen, wie Daten zu senden, durchzuführen. Das fürht natürlich zu enormer Geschwindigkeitsverbesserung. PThreads oder weiter Möglichkeiten sind hier die Stichworte.

So nun zu dem etwas simpleren Java Client :-P und ihr werdet sehen unter Java gestaltet sich das ganze wirklich leichter und lässt sich schneller verstehen ;)


//File Client;java
import java;net;*; // für Sockets
import java;io;*; // für die Exceptions

class Client
{
public static void main( String[] args ){
Socket client = null; // wir brauchen einen Socket der als Client fungieren soll
try{
client = new Socket( "localhost", 7777 ); // wir erstellen einen neuen Socket und verbinden uns zu einer IP Adresse an einem bestimmten Port
OutputStream out = client;getOutputStream(); // wir bersorgen uns sozusagen von diesem Client den Output, um Daten senden zu können
BufferedReader in = new BufferedReader(new InputStreamReader(
client;getInputStream())); // man könnte jetzt denken, "Junge warum nehmen wir hier nicht auch einfach den InputStream?!?". Ist eine Möglichkeit, nur wir wollen mit dem C - Server kommunizieren, und dazu benötigt man am besten einen BufferedReader (meines Wissens nach). Für only Java Programme kann man auch den direkten InputStream verwenden also: InputStream in = client;getInputStream();
String get = "Hi"; // der Text den wir senden wollen
out;write(get;getBytes()); // Wir müssen diesen Text in Bytes schicken, denn als argument werden Bytes von write verlangt
String result; // dort wird der empfangene Text gespeichert
while ((result = in;readLine()) != null) {
System;out;println( result );
/*wir lesen den empfangenen Text schrittwise aus, wenn wir dies nicht schrittweise machen würden, sondern das ganze einfach ohne while Schleife würden wir immer nur die erste Zeile erhalten. D;h. wenn der Server Beispielsweise sendet:
"erste Zeile
zweite Zeile"
empfangen wir ohne diese Schleife nur "erste Zeile"*/
}
// Fehlerbehandlung
}catch ( UnknownHostException e ) {
e;printStackTrace(); // unbekannter host? Wenn dann bitte die Fehlermeldung ausgeben
}catch ( IOException e ) {
e;printStackTrace(); // andere Exceptions?
}finally{ //wenn alles ok ist,dann..
if ( client != null ) //können wir den Client schließen
try { client;close(); } catch ( IOException e ) { e;printStackTrace(); } // Wenn ein Fehler auftritt beim schließen des Socket, dann bitte die Fehlermeldung ausgeben
}
}
}


kurz und knackig ;) Ich hoffe dieses Tutorial hat euch ein bisschen in die Socketprogrammierung eingeführt und Lust erweckt auf mehr :). Also ich finde es ist ein sehr schönes Thema, besonders man hat soo viele Anwendungsmöglichkeiten damit. Man kann FTP-Clients schreiben, simple Browser, aber auch simple Portscanner und das ist manchmal ganz nützlich wenn ihr mal nicht DAS Programm findet um einen Internetservice zu testen, baut euch euer eigenes Programm ;)

greetz schiene

Informationsquellen: "Grundkurs - Socketprogrammierung mit C unter Linux" und "Java ist auch eine Insel"

Hardware Preisvergleich | Amazon Blitzangebote!

Videos zum Thema
Video Loading...
Ähnliche Themen zu [C/C++] C Server + Java Client [Einführung - Socketprogrammierung]
  • [Java] Socket&Client
    Heyho, Ich will einen einfachen Clienten und SocketServer programmieren. der Client kann nacheinander eingaben tätigen und der Server wertet diese aus. Falls beim Clienten z;B. "esc" eingegeben wird. soll alles beendet werden. Server: package SocketProgrammierung_SV; import java;net;*; import j [...]

  • [Java] SFTP Client
    Hey, ich muss ein Programm schreiben, welches über SFTP daten auf nem Server synchronisiert. Hab bis jetzt das JSCH Zeug von JCraft verwendet, hat auch fast alles geklappt. Aber: Das Programm soll überprüfen können ob eine gleichnamige Datei auf dem Server, möglicherweise in einer neuen Versi [...]

  • [C/C++] Pipe-Server/Controll Client soll Funktionen auf Server ausführen
    Moin - zuersteinmal mein vorhaben... Ich möchte einen Pipe-Server erstellen mit dem es möglich ist ein Struct zu versenden welches wie folgt aussehen könnte... struct SendOverPipe Um noch genauer zu werden ich möchte das der Client über eine Nachricht an den Server eine Funktion mit Pa [...]

  • [Java] Datei von Client zum Server übertragen --> Weiterleitung an Clients
    Hi! Ich möchte sehr gerne von einem Client aus eine Datei mit nem Filechooser öffnen und diese soll dann zum Server geschickt werden. Dieser soll die Datei dann an alle Clients weiterleiten... Wie bekomme ich das hin? Habe schon so einige Anleitungen gefunden - aber das Problem ist, dass ich [...]



raid-rush.ws | Imprint & Contact pr