Hura es geht, Netzen unter Linux
- From: Dirk Wolfgang Glomp <dirk@xxxxxxxxxxxxxxxxxxx>
- Date: Thu, 10 Nov 2005 08:28:48 +0100
Hallo NG.
Ich bin jetzt endlich mit dem Programmieren unter Linux angefangen.
Dafür bekam ich Hilfe von meinem Neffen,
der mir u.a. dafür diese beiden Beispiele zuschickte.
;---------------------------------------------
;;; Beispiel-Netzwerk-Code fuer Dirk
;;;
;;; (c) 2002 FaUl
;;;
;;; Server Seite: es wird ein Server-socket auf port 12355 erstellt und
;;; gewartet bis ein Client verbunden hat. Dann wird "Hello, World!"
gesendet.
section .fini ; fini wird am ende ausgefuehrt, wenn man nicht
mov eax, 1 ; vorher mit syscall 1 (exit) ausgestiegen ist
mov ebx, 0
int 0x80 ; exit
section .text
global _start ; entry point exportieren
_start: ; entry point
;; socket erstellen... in C: >>x = socket (PF_INET, SOCK_STREAM, 0);<<
mov eax, 102 ; syscall nr: socketcall
mov ebx, 1 ; socketcall-type: socket()
mov ecx, sockopts ; options von socket()
int 0x80 ; syscall
;;; socketcall ist ein bischen ekelhaft im aufruf. In C gibt es verschiedene
;;; library-funktionen um einen Socket zu erstellen, zu verbinden, etc...,
;;; auf syscall-ebene wird das alles auf ein syscall reduziert: socketcall
;;; in /usr/include/linux/net.h sind die socketcall-types hinterlegt.
;; ausgabe vom fd, ist nicht wichtig
mov [bindopts], eax ; fd schonmal als arg fuer connect...
add eax, 0x30 ; in eax kommt der filedeskriptor, den man
mov byte [x+xs - 2], al ; erstellt hat, die zahl zu einem ASCII-Wert
; machen
mov eax, 4 ; und den ausgeben... syscall nr: write
mov ebx, 1 ; ausgeben auf fd 1: stdout
mov ecx, x ; pointer auf auszugebenen string
mov edx, xs ; laenge des strings
int 0x80 ; syscall
;;; an port bind()en
mov eax, 102 ; wieder socketcall
mov ebx, 2 ; socketcall-type: bind()
mov ecx, bindopts ; options von connect()
int 0x80 ; bind()et
;; in eax ist der returnwert, um fehler abzufangen sollte man den
;; auswerten
;;; status auf listen() setzen (server-socket)
mov eax, 102 ; you got it: socketcall
mov ebx, 4 ; socketcall-type: listen()
mov ecx, [bindopts] ; socket holen
mov [cadin], ecx ; socket in options packen
mov dword [cadin + 4], 1; backlog
mov ecx, cadin ; optionen...
int 0x80 ; listen now
;;; und einkommende verbindungen accept()en
mov eax, 102 ; jaja, socketcall :)
mov ebx, 5 ; socketcall-type: accept()
mov dword [bindopts + 4], cadin; nicht mehr sadin sondern jetzt cadin
mov dword [bindopts + 8], casize; in cadin kommt die client-ip
mov ecx, bindopts ; und der sourceport rein;
int 0x80 ; wartet bis jemand verbunden hat und gibt dann
; nach eax neuen fd
mov ebx, eax ; accept()ed neuer client socket, jetzt wie fd
; zu benutzen...
mov eax, 4 ; Syscall nr: write
mov ecx, data ; was
mov edx, size ; wieviel
int 0x80 ; in socket schreiben
section .data
x db "filedescriptor: = ",00,10
xs equ $ - x
data db "Hello, World!",10
size equ $ - data
sockopts dd 02,01,00 ; optionen von socket().
; PF_INET, SOCK_STREAM, 0...
; (in /usr/include/linux/socket.h ist PF_INET
; und die anderen moeglichkeiten dokumentiert )
bindopts dd 00,sadin,16 ; optionen von bind(): int sockfd, pointer
; auf eine struct sockaddr_in (in
; /usr/include/netinet/in.h definiert) und die
; groesse dieser struktur als 3. argument.
;; struct sockaddr_in:
;; 2 byte type (2 = PF_INET, siehe oben)
;; 2 byte port
;; 4 byte ip-addresse addresse
;; 8 byte muell, um auf 16bytes zu kommen
;; WICHTIG: IP arbeitet mit big-endian, Intel ix86 mit little-endian,
;; man muss also konvertieren um keine endianess-fehler zu bekommen...
;; beispiel struct:
;; sockaddr_in.sin_type = PF_INET
;; sockaddr_in.sin_port = 12347
;; sockaddr_in.sin_addr = 0 (INADDR_ANY)
sadin dw 0x2,0x4330,0x0,0x0,0,0,0
cadin times 8 dw 0 ; auch eine struct sockaddr_in, wird von
; accept() ausgefuellt
casize dd 16 ; accept will einen pointer auf die laenge
; keine ahnung warum, braindamaged, vermutlich!
;------------------------------------------------------
;; Beispiel-Netzwerk-Code fuer Dirk
;;
;; (c) 2002 FaUl
;;
;; Client Seite: es wird zu einem Server verbunden und alles, was vom
;; der server sendet und vom client empfangen wird, wird ausgegeben.
section .fini ; fini wird am ende ausgefuehrt, wenn man nicht
mov eax, 1 ; vorher mit syscall 1 (exit) ausgestiegen ist
mov ebx, 0
int 0x80 ; exit
section .text
global _start ; entry point exportieren
_start: ; entry point
;; socket erstellen... in C: >>x = socket (PF_INET, SOCK_STREAM, 0);<<
mov eax, 102 ; syscall nr: socketcall
mov ebx, 1 ; socketcall-type: socket()
mov ecx, sockopts ; options von socket()
int 0x80 ; syscall
;; socketcall ist ein bischen ekelhaft im aufruf. In C gibt es verschiedene
;; library-funktionen um einen Socket zu erstellen, zu verbinden, etc...,
;; auf syscall-ebene wird das alles auf ein syscall reduziert: socketcall
;; in /usr/include/linux/net.h sind die socketcall-types hinterlegt.
;; ausgabe vom fd, ist nicht wichtig
mov [connopts], eax ; fd schonmal als arg fuer connect...
add eax, 0x30 ; in eax kommt der filedeskriptor, den man
mov byte [x+18], al ; erstellt hat, die zahl zu einem ASCII-Wert
; machen
mov eax, 4 ; und den ausgeben... syscall nr: write
mov ebx, 1 ; ausgeben auf fd 1: stdout
mov ecx, x ; pointer auf auszugebenen string
mov edx, 20 ; 20 bytes ausgeben (laenge des strings)
int 0x80 ; syscall
mov eax, 102 ; wieder socketcall
mov ebx, 3 ; socketcall-type: connect()
mov ecx, connopts ; options von connect()
int 0x80 ; syscall
sockread:
mov ebx, [connopts] ; socket, jetzt wie fd zu benutzen...
mov eax, 3 ; Syscall nr: read
mov ecx, data ; dahin lesen
mov edx, 1024 ; max 1024 bytes lesen
int 0x80 ; einlesen
or eax, eax ; ist socket von remote geschlossen worden?
jz fertig ; ok, wir sind fertig
mov ebx, 1 ; stdout
mov edx, eax ; genausoviele bytes ausgeben wie eingelesen
mov eax, 4 ; Syscall nr: write
mov ecx, data ; data ausgeben
int 0x80 ; ausgeben
jmp sockread ; und weiter im text
fertig:
section .data
x db "filedescriptor: = ",00,10
data times 1024 db 00
sockopts dd 02,01,00 ; optionen von socket().
; PF_INET, SOCK_STREAM, 0...
; (in /usr/include/linux/socket.h ist PF_INET
; und die anderen moeglichkeiten dokumentiert )
connopts dd 00,sadin,16 ; optionen von connect(): int sockfd, pointer
; auf eine struct sockaddr_in (in
; /usr/include/netinet/in.h definiert) und die
; groesse dieser struktur als 3. argument.
;; struct sockaddr_in:
;; 2 byte type (2 = PF_INET, siehe oben)
;; 2 byte port
;; 4 byte ip-addresse addresse
;; 8 byte muell, um auf 16bytes zu kommen
;; WICHTIG: IP arbeitet mit big-endian, Intel ix86 mit little-endian,
;; man muss also konvertieren um keine endianess-fehler zu bekommen...
;; beispiel struct:
;; sockaddr_in.sin_type = PF_INET
;; sockaddr_in.sin_port = 12355
;; sockaddr_in.sin_addr = 192.168.0.2
sadin dw 0x2,0x4330,0xA8C0,0x0200,0,0,0,0
;------------------------------------------------------
nasm -f elf -o server_o server.asm
ld -s -o server server_o
nasm -f elf -o client_o client.asm
ld -s -o client client_o
....
Der erste Server-Teil muß zuerst gestartet werden,
da im zweiten Client-Teil noch keine Fehler abgefangen werden,
es sonst zu einer ungewollten fehlerhaften Ausgabe kommt.
Die IP(in sadin) des client-rechners muß ggf. angepasst werden.
(hier 0xA8C0,0x0200 für 192.168.0.2)
;------------------------------------------------------
Ich schätze mal, mit Windows geht das Netzen nicht so elegant
und rel. übersichtlich wie diese Beispiele für Linux, oder?
Obwohl ich auch diese beiden Listings noch nicht so ganz begreife,
da ich sonst nur unter purem DOS mit MASM gearbeitet habe,
denke ich damit kann ich weiterarbeiten.
.....
Nächstes Lernziel: Grafik-Ausgabe mit Frame Buffer
Habe hierfür noch nicht gesucht.
Wer kann hierfür ein kleines Demo posten,
welches ebenso elegant ausschaut und _nicht_ zu C-artig ist
(net.h habe ich gar nicht entziffern können)?
Kann ich mittels FB ebenso wie mit VESA3 unter DOS,
einen linearen true color mode mit eigenen CRT-values benutzen?
Dirk
.
- Prev by Date: Re: Wo kommen die "Import-Libarys" her?
- Next by Date: Re: Intel FPU
- Previous by thread: Wo kommen die "Import-Libarys" her?
- Next by thread: Re: Intel FPU
- Index(es):
Relevant Pages
|