amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > Beispiel zu Datenübertragung via Netzwerk [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

02.02.2007, 14:07 Uhr

geit
Posts: 332
[Ex-Mitglied]
Gibt es ein einfaches Beispiel, wie man via bsdsocket.library Daten übertragen kann?

Ich möchte ein kleines Programm schreiben, das über einen Port kleine Datenpakete hin und her schiebt. Das Programm soll dabei auf beiden Rechnern zum Einsatz kommen.

Bei der Funktionsvielfalt der bsdsocket.library und meinen beschränkten Netzwerkkenntnissen blick ich das nicht so ganz. :)

TCP: oder externe Libraries möchte ich nicht benutzen.

Geit

[ - Antworten - Zitieren - Direktlink - ]

02.02.2007, 17:09 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Würd mich auch mal interessieren.

Ich selbst nutze eine High-Level Bibliothek von Amiblitz, die kann aber nicht auf einen Port hören, also man kann nur Clients schreiben (Browser, Email), aber keinen Server.
Wenn auf beiden Seiten ein Amiga laufen soll, muss aber einer der beiden den Server spielen, bzw. auf einen Port hören.

Gibts dazu irgendwo Beispiel sourcen ?

--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

03.02.2007, 18:39 Uhr

Honitos
Posts: 200
Nutzer
Moin !

Ich habe das ganze auch mal mittels der BSDsocket.library unter AmiBlitz ausprobiert. Bei der Portierung bin ich aber nicht weit gekommen, jedenfalls stürtzte der CLient immer ab.

Ich habe mich dabei an folgender ARbeitsunterlage langgehangelt:
http://www.ibr.cs.tu-bs.de/courses/ws0102/vs/VS-0102-Uebung2.pdf

Vielleicht kommt Ihr ja weiter !

Gruss,
Sven

[ Dieser Beitrag wurde von Honitos am 03.02.2007 um 18:40 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

03.02.2007, 18:57 Uhr

Georg
Posts: 107
Nutzer
@geit:

Google mal nach "netcat".






[ - Antworten - Zitieren - Direktlink - ]

07.02.2007, 12:16 Uhr

geit
Posts: 332
[Ex-Mitglied]

So ich hab mal was zusammengebastelt. Es funktioniert auch Teilweise.

Zur erklärtung. TCP_Init() wird beim Programmstart ausgeführt. TCP_Open *in* der Programmschleife, damit z.B. später in der WBStart keine Probleme auftreten, wenn es die bsdsocket.library noch nicht gibt. Daher kann die Funktion mehrfach gestartet werden.

Das die Packete nicht in Sendereihenfolge eintreffen, ist wohl Netzwerk bedingt und ich komme um eine Sortierung nicht rum. Oder sehe ich das falsch?

IMHO können keine Packete verloren gehen, sondern nur auf sich warten lassen. Richtig?

Manchmal passiert es, dass ich einen Neustart des NetStacks machen muß, damit ich ohne Fehler wieder was einhängen kann, also scheint meine Routine nicht ganz optimal zu sein. ;)

Kommentare, Anmerkungen sind willkommen. so ganz blick ich das immer noch nicht.

Geit
C code:
/* TCP stuff */

int                tcp_socketclientinfd;
struct sockaddr_in tcp_socketclient;
ULONG              tcp_sizeclient;

int                tcp_socketserverfd;
struct sockaddr_in tcp_socketserver;

int                tcp_socketclientoutfd;
struct sockaddr_in tcp_socketclientout;

BOOL               tcp_pipein;
BOOL               tcp_pipeout;


struct List paketlist;
struct TCPMessage *lasttcpmsg;

#define SERIALBUFFER_SIZEOF 8192

BYTE  serialbuffer[ SERIALBUFFER_SIZEOF ];
ULONG serialindex;


/* TCP Init */

void TCP_Init( void )
{
	List_Init( &paketlist );

	tcp_socketserverfd = -1;
	tcp_socketclientoutfd  = -1;

}

/* TCP Open */

ULONG TCP_Open(void)
{
ULONG arg;

	debug("TCP: setup...n");
	if( !SocketBase ) {
		SocketBase = (struct Library *) OpenLibrary( "bsdsocket.library", 4);
		debug("tried to open bsdsocket.libraryn");
	}
	if( SocketBase ) {

/* init incoming data pipe if needed */

		if( !tcp_pipein ) {
			if( -1 != (tcp_socketserverfd = socket( AF_INET, SOCK_STREAM, 0)) ) {

				/* fill sockaddr_in and bind socket to local port */

				tcp_socketserver.sin_family      = AF_INET;
				tcp_socketserver.sin_port        = htons(VKM_PORT);
				tcp_socketserver.sin_addr.s_addr = htonl(INADDR_ANY);
				//memset(&(tcp_socketserver.sin_zero), '', 8);
				arg = 1;
				if( -1 != IoctlSocket( tcp_socketserverfd, FIONBIO, &arg) ) {
					debug("TCP: in socket non blocking enabledn");
					if( -1 != bind( tcp_socketserverfd, (struct sockaddr *) &tcp_socketserver, sizeof(struct sockaddr) ) ) {
						debug("TCP: in socket bond to portn");
						if( -1 != listen( tcp_socketserverfd, 10) ) {
							debug("TCP: in socket listening to port - ready for actionn");
							tcp_pipein = TRUE;
						}
					}
				}
			}
			if( !tcp_pipein && tcp_socketserverfd != -1 ) { /* shut down pipe due error */
				debug("TCP: Closing in socket due failn");
				CloseSocket( tcp_socketserverfd );
				tcp_socketserverfd = -1;
			}
		}

/* init outgoing data pipe */

		if( !tcp_pipeout && readargs_array[ARG_IP ] ) {
			if( -1 != (tcp_socketclientoutfd = socket(AF_INET, SOCK_STREAM, 0)) ) {
				/* fill sockaddr_in struct for connection */
				tcp_socketclientout.sin_family      = AF_INET;
				tcp_socketclientout.sin_port        = htons( VKM_PORT);
				tcp_socketclientout.sin_addr.s_addr = inet_addr( (STRPTR) readargs_array[ARG_IP ]);
				//memset(&(tcp_socketfddest.sin_zero), '', 8);
				if( -1 != connect( tcp_socketclientoutfd, (struct sockaddr *) &tcp_socketclientout, sizeof(struct sockaddr)) ) {
					debug("TCP: out socket connected - ready for actionn");
					tcp_pipeout = TRUE;
				}
			}
			if( !tcp_pipeout && tcp_socketclientoutfd  != -1 ) { /* shut down pipe due error */
				debug("TCP: Closing in socket due failn");
				CloseSocket( tcp_socketclientoutfd );
				tcp_socketclientoutfd = -1;
			}
		}
	}
	debug("TCP: setup donen");
return( 0 );
}

/* TCP_Close */

void TCP_Close(void)
{
struct TCPMessage *tcpmsg;

/* tcp */

	if( tcp_pipein ) {
		CloseSocket( tcp_socketserverfd );
	}
	if( tcp_pipeout ) {
		CloseSocket( tcp_socketclientoutfd );
	}
	if( SocketBase ) {
		CloseLibrary( (struct Library *) SocketBase );
		SocketBase = NULL;
	}

/* free used memory */

	if( paketlist.lh_Head ) {

		while( (tcpmsg = (APTR) paketlist.lh_Head)->tcp_Node.ln_Succ ) {
			TCP_UnqeuePaket ( tcpmsg );
		}
	}

}

/* TCP_TransferHandle */

void TCP_TransferHandle( void )
{
ULONG num;

	if( tcp_pipeout ) {
		if( (lasttcpmsg = (APTR) paketlist.lh_Head)->tcp_Node.ln_Succ ) {
			num = send( tcp_socketclientoutfd, &lasttcpmsg->tcp_Command, lasttcpmsg->tcp_Command.cmd_Size, 0 );
			if( num != -1 && num != 0 ) {
				TCP_UnqeuePaket( lasttcpmsg ); /* remove packet from packet list */
				debug("TCP: Send %ld Bytesn", num);
			}
		}
	}
	if( tcp_pipein ) {
		if( !tcp_socketclientinfd || tcp_socketclientinfd == -1 ) {
			tcp_socketclientinfd = accept( tcp_socketserverfd, (struct sockaddr *)&tcp_socketclient, &tcp_sizeclient);
			//debug("accept: %ldn",tcp_socketclientinfd );
		}
		if( SERIALBUFFER_SIZEOF - serialindex ) {
			if( -1 != (num = recv( tcp_socketclientinfd, &serialbuffer[ serialindex ], SERIALBUFFER_SIZEOF - serialindex , 0) )) {
#if DEBUG
				if( num ) {
					debug("TCP: got %ld Bytes: %80lhn", num, &serialbuffer[ serialindex ]);
				}
#endif
				serialindex += num;
			}
		}
		//TCP_HandleBuffer(); /* read and proccess packets from cache */
	}
}




[ Dieser Beitrag wurde von geit am 07.02.2007 um 12:20 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

07.02.2007, 22:39 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Das die Packete nicht in Sendereihenfolge eintreffen, ist wohl Netzwerk bedingt und ich komme um eine Sortierung nicht rum. Oder sehe ich das falsch?

Da bist Du auf dem Holzweg. IP basiert auf Paketen und UDP stellt eine paketorientierte Verbindungen zur Verfügung. TCP stellt auf IP aufbauend streamorientierte Verbindungen zu Verfügung. Das heißt nicht nur, dass es sich um das Neu-Anfordern von verlorengegangenen Paketen kümmert und sie in die richtige Reihenfolge bringt, sondern es heißt auch, das der Begriff Paket überhaupt nicht mehr in Deiner Anwendung auftauchen sollte.

Du solltest also, je nach dem wie die Amiga-Fassung davon aussieht, eine Funktion namens read oder recv (oder auch socket_read oder socket_recv) finden und benutzen.

Andersherum dann write oder send (socket_write oder socket_send).

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

08.02.2007, 11:11 Uhr

geit
Posts: 332
[Ex-Mitglied]

Ich glaube du hast mich da leicht missverstanden.

Obige Funktionen laufen auf zwei Rechnern. (Amithlon und MOS)

Jedes der Programme verschickt ermittelte Daten/Kommandos an das andere.

Da die Daten allerdings zur Laufzeit ermittelt werden, ergeben sich daraus "Pakete". Jedes Paket wird mit
send() verschickt und daten via recv() empfangen. Wenn ich jetzt 5 mal send mit einem paket anwende, dann kommen auf dem anderen Rechner 5 Pakete an, die aber durcheinander sind. Teilweise bekomme ich 2 oder 3 zusammenhängend (STREAM), aber teilweise werden die einzeln angeliefert.

So kommt das zweite mit send() verschickte Paket z.B. auch als 5. an.

Das passiert mit den Routinen die oben abgebildet sind.

Das ermitteln der einzelnen Pakete in dem Strom ist kein Problem. Da ich das ganze eventuell auch seriell machen will, muß ich mir das sowieso offen halten.

Lösungen und Tips sind willkommen!

Geit

[ - Antworten - Zitieren - Direktlink - ]

08.02.2007, 13:26 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Wenn ich es richig Verstanden habe, sind deine "Packete" bereits in der "Anwender Schicht" (7 Schichten Model), also z.B. eine GIF Bild auf einer Website kommt als ein Packet an (was natürlich in vielen kleine TCP Packets geschickt wird).
Die Reihenfolge ist dann natürlich nicht vorhersehbar.
Das wäre dann Aufgabe des darüber liegenden Protokolls, was du dann erfinden musst, z.B. kann man eine Nummerierung oder einen Zeitstempel mitschicken.

Ich werde mir das Beispiel mal genau ansehen und evtl. in Amiblitz übertragen. Das wäre ein guter Ersatz für die tcp.include, weil die nur aktiv eine Verbindung aufbauen kann, aber nicht auf einer Verbindung warten. Dann könnte man endlich Online Spiele realisieren, ohne marquee.lib oder sowas, was nicht mehr entwickelt wird.

@Honitos
Was hast du bereits gemacht ? Evtl. kannst du mir das schicken.


--
Thilo Köhler, Author von:
HD-Rec, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, TKUnpacker
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

08.02.2007, 18:40 Uhr

Honitos
Posts: 200
Nutzer
@Thilo:
Habe ich Dir per Mail geschickt!

[ - Antworten - Zitieren - Direktlink - ]

08.02.2007, 20:23 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Jedes der Programme verschickt ermittelte Daten/Kommandos an das andere.

Da die Daten allerdings zur Laufzeit ermittelt werden, ergeben sich daraus "Pakete". Jedes Paket wird mit
send() verschickt und daten via recv() empfangen. Wenn ich jetzt 5 mal send mit einem paket anwende, dann kommen auf dem anderen Rechner 5 Pakete an, die aber durcheinander sind.


Du solltest Dich erst einmal entscheiden, was Du nun wirklich willst, TCP oder Pakete. Es geht nur eins von beiden.

Wenn Du das geschafft hast, kannst Du Dich auch entscheiden, ob Du die Funktionen für TCP oder für Pakete verwendest.

Zitat:
Original von Der_Wanderer:
Wenn ich es richig Verstanden habe, sind deine "Packete" bereits in der "Anwender Schicht" (7 Schichten Model), also z.B. eine GIF Bild auf einer Website kommt als ein Packet an (was natürlich in vielen kleine TCP Packets geschickt wird).


Das hast Du nicht richtig verstanden. Ein GIF-Bild auf einer Webseite wird via http übertragen, was wiederum via tcp realisiert wird. Erst unterhalb von von tcp, also bei ip werden Pakete verschickt.
Ein GIF-Bild bleibt eine Datei und wird in einem Datenstrom, bestehend aus http-header, gefolgt von den eigentlichen Daten (und optional seit http 1.1 gefolgt von weiteren headern und weiteren Dateien), verschickt.

mfg
--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

13.02.2007, 13:09 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Zitat:
Jedes der Programme verschickt ermittelte Daten/Kommandos an das andere.

Da die Daten allerdings zur Laufzeit ermittelt werden, ergeben sich daraus "Pakete". Jedes Paket wird mit
send() verschickt und daten via recv() empfangen. Wenn ich jetzt 5 mal send mit einem paket anwende, dann kommen auf dem anderen Rechner 5 Pakete an, die aber durcheinander sind.


Du solltest Dich erst einmal entscheiden, was Du nun wirklich willst, TCP oder Pakete. Es geht nur eins von beiden.


Ob ich die empfangenen Dateien wieder in Packete teile ist doch schnuppe. Ich will nur Daten verschicken und am anderen Ende in einem
zusammenhängenden Puffer empfangen. Also wie bei einer seriellen übertragung.

Aber wenn die Daten auf dem Quellrechner nicht schnell genug kommen, dann kommen hinten am zweiten Rechner mehrere Packete in unterschiedlicher Reihenfolge an. Das kann ich anhand der Daten im Puffer lesen.

Zitat:
Wenn Du das geschafft hast, kannst Du Dich auch entscheiden, ob Du die Funktionen für TCP oder für Pakete verwendest.
Warum so schroff? Vielleicht könntest du mal sagen, welche Funktionen das sind? Send() und Recv() scheinen es jedenfalls nicht zu sein.

Zitat:
Zitat:
Wenn ich es richig Verstanden habe, sind deine "Packete" bereits in der "Anwender Schicht".
Das hast Du nicht richtig verstanden.

Doch hat er. Der serielle Puffer wird von meinem Programm in Pakete zerlegt, die dann IM Rechner als solche behandelt werden.

Mein Problem ist wie bekomme ich das hin, das die Daten hintereinander
reinkommen und sich nicht auf der Datenautobahn überholen. Das passiert nämlich
derzeit. Ich verschicke schnell hintereinander zwei meiner Packete (Also zweimal
eine beliebige Datenmenge) einzeln mit send() und sie kommen richtig und mit
einem recv() auf der anderen Seite an. Dann kommen nochmal zwei Pakete (also
wieder zwei beliebige Datenmengen) die wieder einzeln abgeschickt werden und die
kommen verkehrt an, weil die gegenstelle zwei mal recv() aufruft.

Was muß ich an meinem Programm ändern, damit ich eine übertragung erzeuge, die
einer seriellen Verbindung gleicht.

Geit

[ - Antworten - Zitieren - Direktlink - ]

13.02.2007, 13:49 Uhr

thomas
Posts: 7716
Nutzer
Zitat:
Aber wenn die Daten auf dem Quellrechner nicht schnell genug kommen, dann kommen hinten am zweiten Rechner mehrere Packete in unterschiedlicher Reihenfolge an. Das kann ich anhand der Daten im Puffer lesen.

Die Daten, die du mit recv() liest, kommen exakt in der gleichen Reihenfolge an, wie der andere Rechner sie mit send() abgeschickt hat. Einzelne send()s können in mehrere recv()s münden, genauso wie mehrere send()s zu einem recv() zusammengefaßt werden können. Aber der Datenstrom insgesamt bleibt intakt.

Wenn deine Daten durcheinander kommen, dann hast du Schrott programmiert.

Gruß Thomas

--
Email: thomas-rapp@web.de
Home: thomas-rapp.homepage.t-online.de/

[ - Antworten - Zitieren - Direktlink - ]

18.02.2007, 10:35 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von geit:
Ob ich die empfangenen Dateien wieder in Packete teile ist doch schnuppe. Ich will nur Daten verschicken und am anderen Ende in einem
zusammenhängenden Puffer empfangen. Also wie bei einer seriellen übertragung.

Wenn Du eine serielle Übertragung willst, dann rede auch nicht von Paketen. Es steht Dir natürlich frei, die Wörter unserer Sprache beliebig sinnentstellt zu verwenden, dann darfst Du Dich aber nicht darüber beschweren, wenn die Kommunikation mit anderen Menschen nicht funktioniert. TCP ist eine serielle Verbindung.
Zitat:
Zitat:
Das hast Du nicht richtig verstanden.

Doch hat er. Der serielle Puffer wird von meinem Programm in Pakete zerlegt, die dann IM Rechner als solche behandelt werden.

Er sprach von einem Gif-Bild auf einer Webseite. Das hat offensichtlich nichts damit zu tun, was Dein Programm macht.

Alles weitere hat thomas schon gesagt.

mfg

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > Beispiel zu Datenübertragung via Netzwerk [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.