Einige grundlegende Funktionen der Netzwerkprogrammierung: Dies ist auch der grundlegende Schritt zur Realisierung der TCP-Protokollkommunikation. Der Implementierungscode befindet sich am Ende. Die IP muss zur Kommunikation in Ihre eigene IP geändert werden. 1. Erstellen Sie einen SocketFunktionsprototyp: #include <sys/types.h> #include <sys/socket.h> int socket(int-Domäne, int-Typ, int-Protokoll); Parameterliste: Der Domänenparameter hat die folgenden Werte:
Werte vom Typ:
Protokollwert:
Die Funktion dient zum Erstellen eines Sockets mit einem bestimmten Format und zum Zurückgeben seines Deskriptors. Bei Erfolg wird der Deskriptor zurückgegeben, andernfalls wird -1 zurückgegeben. 2. Socket-Bindung bindenFunktionsprototyp: #include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *meine_adresse, socklen_t addrlen); Parameterliste: sockfd ist der zuvor erstellte Socket-Deskriptor my_addr ist ein Zeiger auf eine allgemeine Socket-Struktur. Bei der TCP-Protokollprogrammierung wird normalerweise die Struktur sockaddr_in verwendet. Der Inhalt der Struktur ist wie folgt; Struktur socketaddr_in { unsigned short int sin_family; //Füge AF_INTE für die entsprechende Adressfamilie IP v4 ein uint16_t sin_port; //entsprechende Portnummer struct in_addr sin_addr; //entsprechende IP-Adresse unsigned char sin_zero[8]; }; Struktur in_addr { uint32_t s_addr; }; addrlen ist die Größe der obigen Struktur, die mit sizeof ermittelt werden kann; Bevor Sie die Bind-Funktion verwenden, müssen Sie eine Struktur vom Typ sockaddr_in erstellen, die Serverinformationen in der Struktur speichern und dann den erstellten Socket daran binden. Geben Sie bei Erfolg 0 und bei einem Fehler -1 zurück. Wenn Sie die Portnummer und die IP festlegen, löschen Sie zuerst die Struktur. Wenn die Hauptfunktion Parameter übergibt, liegen die entsprechende Portnummer und die IP im Zeichenfolgenformat vor und müssen mithilfe einer Funktion konvertiert werden. Das Konvertierungsformat lautet wie folgt: Zeichenport[]="8888" char ip[]="192.168.1.1" Struktur sockaddr_in seraddr' seraddr.sin_port = htos(atoi(Port)) seraddr.sin_addr.s_addr = inet_addr(ip); 3. Erstellen Sie einen Listener; hören Sie zuFunktionsprototyp: int listen(int fd, int Rückstand); Parameterliste: fd ist der zu überwachende Socket-Deskriptor; Backlog ist die Größe der Überwachungswarteschlange; (1) Nach der Ausführung von „listen“ wechselt der Socket in den passiven Modus. (2) Wenn die Warteschlange voll ist, werden neue Verbindungsanfragen abgelehnt. Der Client erhält einen Verbindungsfehler WSAECONNREFUSED. (3) Das Ausführen von „listen“ auf einem Socket, der bereits lauscht, hat keine Auswirkungen. 4. Warten Sie, bis die Verbindung akzeptiert wirdFunktionsprototyp: #include <sys/socket.h> int accept(int s, Struktur sockaddr * Adresse, int * Adresslänge); Wenn wir die Bind-Funktion vergleichen, können wir feststellen, dass die Parameter der beiden fast gleich sind, aber die Adresse in Accept wird nicht durch const geändert, d. h. die Adresse wird zum Speichern der Adressinformationen des verbundenen Clients verwendet und die Größe der Adresse wird beim Yangsaddlen zurückgegeben. Daher gibt die Accept-Funktion den Dateideskriptor des verbundenen Clients zurück und speichert die Adressinformationen des Clients in einer neuen sockaddr_in-Struktur; wenn die Verbindung fehlschlägt, gibt sie -1 zurück; 5. Senden und Empfangen von Nachrichten senden und empfangenFunktionsprototyp int send( SOCKET s, const char FAR *buf, int len, int flags ); int recv( SOCKET s, char FAR *buf, int len, int flags); Die Parameter dieser Funktion sind:
Der Sendevorgang : Hier beschreiben wir nur den Ausführungsfluss der Sendefunktion des synchronen Sockets. Wenn Sie diese Funktion aufrufen, vergleicht man zuerst die Länge der Daten, die mit der Länge des Sendungspuffers gesendet werden sollen OCOL hat nicht begonnen, die Daten im Send -Puffer von S zu senden, oder es gibt keine Daten im Send -Puffer von S und vergleicht den verbleibenden Speicherplatz mit Len. bis zum anderen Ende der Verbindung, aber das Protokoll. Wenn die Sendefunktion die Daten erfolgreich kopiert, gibt sie die tatsächliche Anzahl der kopierten Bytes zurück. Wenn beim Kopieren der Daten ein Fehler auftritt, gibt Send SOCKET_ERROR zurück. Wenn die Netzwerkverbindung getrennt wird, während Send auf die Datenübertragung durch das Protokoll wartet, gibt die Sendefunktion ebenfalls SOCKET_ERROR zurück. Es ist zu beachten, dass die Sendefunktion zurückkehrt, nachdem die Daten in buf erfolgreich in den verbleibenden Speicherplatz im Sendepuffer von s kopiert wurden. Zu diesem Zeitpunkt werden die Daten jedoch möglicherweise nicht sofort an das andere Ende der Verbindung übertragen. Wenn während des nachfolgenden Übertragungsvorgangs des Protokolls ein Netzwerkfehler auftritt, gibt die nächste Socket-Funktion SOCKET_ERROR zurück. (Jede Socket-Funktion außer „Senden“ muss warten, bis die Daten im Sendepuffer des Sockets vom Protokoll übertragen wurden, bevor sie fortfahren kann. Wenn während des Wartens ein Netzwerkfehler auftritt, gibt die Socket-Funktion „SOCKET_ERROR“ zurück.) Der Prozess von recv : Hier beschreiben wir nur den Ausführungsfluss der Recv-Funktion des synchronen Sockets. Wenn die Anwendung die Funktion recv aufruft, wartet recv zunächst darauf, dass die Daten im Sendepuffer von s vom Protokoll übertragen werden. Tritt beim Übertragen der Daten im Sendepuffer von s durch das Protokoll ein Netzwerkfehler auf, gibt die Funktion recv SOCKET_ERROR zurück. Befinden sich keine Daten im Sendepuffer von s oder werden die Daten erfolgreich vom Protokoll gesendet, prüft recv zunächst den Empfangspuffer des Sockets s. Befinden sich keine Daten im Empfangspuffer von s oder empfängt das Protokoll Daten, wartet recv, bis das Protokoll die Daten empfangen hat. Wenn das Protokoll mit dem Empfangen der Daten fertig ist, kopiert die Funktion recv die Daten im Empfangspuffer von s nach buf (beachten Sie, dass die vom Protokoll empfangenen Daten größer als die Länge von buf sein können. In diesem Fall muss die Funktion recv mehrmals aufgerufen werden, um alle Daten im Empfangspuffer von s zu kopieren. Die Funktion recv kopiert nur Daten, und der eigentliche Empfang der Daten wird vom Protokoll durchgeführt). Die Funktion recv gibt die Anzahl der tatsächlich kopierten Bytes zurück. Wenn recv während des Kopierens fehlschlägt, wird SOCKET_ERROR zurückgegeben. Wenn das Netzwerk unterbrochen wird, während die recv-Funktion darauf wartet, dass das Protokoll Daten empfängt, wird 0 zurückgegeben. Das TCP-Protokoll selbst ist zuverlässig, aber das bedeutet nicht, dass die Anwendung, die Daten über TCP sendet, unbedingt zuverlässig ist. Unabhängig davon, ob es blockiert ist oder nicht, stellt die Größe der gesendeten Daten nicht dar, wie viele Daten das andere Ende empfängt. Im Sperrmodus besteht der Prozess der Sendefunktion darin, die von der Anwendung angeforderten Daten in den Sendepuffer zu kopieren, zu senden und nach Bestätigung zurückzukehren. Aufgrund der Existenz des Sendepuffers manifestiert sich dies jedoch wie folgt: Wenn die Sendepuffergröße größer als die angeforderte Größe ist, kehrt die Sendefunktion sofort zurück und sendet gleichzeitig Daten an das Netzwerk. Andernfalls sendet Send den Teil der Daten, der nicht im Puffer untergebracht werden kann, an das Netzwerk und wartet auf die Bestätigung des anderen Endes, bevor es zurückkehrt (solange das empfangende Ende die Daten im Empfangspuffer empfängt, wird es bestätigen und muss nicht warten, bis die Anwendung recv aufruft); Im nicht blockierenden Modus kopiert die Sendefunktion die Daten nur in den Puffer des Protokollstapels. Wenn der verfügbare Speicherplatz im Puffer nicht ausreicht, kopiert sie so viel wie möglich und gibt die Größe der erfolgreichen Kopie zurück. Wenn der verfügbare Speicherplatz im Puffer 0 ist, gibt sie -1 zurück und setzt errno auf EAGAIN. 6. Schließen Sie den Socket-Deskriptor closeFunktion:
Wie Dateioperationen ist auch ein Socket eine Datei und muss nach der Verwendung geschlossen werden. 7. C/S-Servermodell basierend auf dem TCP-ProtokollIllustriertes TCP-Modell 8. ImplementierungscodeServer: #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <unistd.h> Typdefinitionsstruktur sockaddr_in SIN; Typdefinitionsstruktur Sockaddr SA; int main(int argc,char *argv[]) { SIN Seradresse; SIN-Cliaddr; int len=sizeof(SIN); //Einen Abhörsocket erstellen int lisfd=socket(AF_INET,SOCK_STREAM,0); wenn(lisfd<0) { perror("Buchse"); Ausfahrt (0); } printf("Socket%d erfolgreich erstellt\n",lisfd); bzero(&seraddr,sizeof(seraddr)); seraddr.sin_family=AF_INET; seraddr.sin_port = htons(8888); seraddr.sin_addr.s_addr = inet_addr("192.168.1.6"); //Socket binden int ret=bind(lisfd,(SA*)(&seraddr),len); wenn(ret<0) { perror("binden"); Ausfahrt (0); } printf("Bindung erfolgreich\n"); //Mit dem Abhören beginnen ret=listen(lisfd,1024); wenn(ret<0) { perror("zuhören"); Ausfahrt (0); } printf("Überwachung erfolgreich\n"); //Auf Verbindung warten und die Informationen zum verbundenen Socket speichern int clifd=accept(lisfd,(SA*)(&cliaddr),(socklen_t *)(&len)); wenn(clifd<0) { perror("akzeptieren"); Ausfahrt (0); } printf("Client %d erfolgreich verbunden\n",clifd); //Char lesen und schreiben readbuf[1024]={0}; char sendbuf[1024]={0}; während(1) { recv(clifd,readbuf,Größe von(readbuf),0); printf("empfangen:%s\n",readbuf); fgets(sendbuf,sizeof(sendbuf),stdin); sende(clifd,sendbuf,sizeof(sendbuf),0); } //Socket schließen close(clifd); schließen(lisfd); gebe 0 zurück; } Kunde: #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <unistd.h> Typdefinitionsstruktur sockaddr_in SIN; Typdefinitionsstruktur Sockaddr SA; int main(int argc,char *argv[]) { SIN Seradresse; //Einen Abhörsocket erstellen int serfd=socket(AF_INET,SOCK_STREAM,0); wenn(serfd<0) { perror("Buchse"); Ausfahrt (0); } printf("Socket%d erfolgreich erstellt\n",serfd); bzero(&seraddr,sizeof(seraddr)); seraddr.sin_family=AF_INET; seraddr.sin_port = htons(8888); seraddr.sin_addr.s_addr = inet_addr("192.168.1.6"); //Verbindung anfordern int ret=connect(serfd,(SA*)(&seraddr),sizeof(SIN)); wenn(ret == -1) { perror("verbinden"); Ausfahrt (0); } printf("Verbindung erfolgreich\n"); //Char lesen und schreiben senbuf[1024]={0}; char readbuf[1024]={0}; während(1) { fgets(senbuf,sizeof(senbuf),stdin); sende(serfd,senbuf,sizeof(senbuf),0); recv(serfd,readbuf,Größe von(readbuf),0); printf("empfangen:%s\n",readbuf); } //Socket schließen close(serfd); gebe 0 zurück; } Dies ist das Ende dieses Artikels über eine kurze Analyse der Netzwerkprogrammierfunktionen von Linux. Weitere relevante Inhalte zu den Netzwerkprogrammierfunktionen von Linux finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: So unterstreichen Sie das A-Tag und ändern die Farbe vor und nach dem Klicken
>>: Gemeinsame Nutzung von zwei Plug-Ins zur Übersetzung von Webseiten
Vorwort Bei der Entwicklung tatsächlicher Projekt...
1. Was ist Scaffolding? 1. Vue-CLI Vue CLI ist ei...
Erstellen des Images Früher haben wir verschieden...
Dieser Artikel zeichnet die Installations- und Ko...
Vorwort Hallo zusammen, ich bin Liang Xu. Bei der...
Inhaltsverzeichnis Einführung 1. Gesamtarchitektu...
Wie üblich posten wir zuerst den Bildeffekt: Das ...
Ich habe in letzter Zeit viel MySQL-bezogene Synt...
1. Gehen Sie zu dem Speicherort, an dem Sie das I...
Szenario mit dem Problem des Seitenumblätterns B ...
Ausführungsproblem zwischen MySQL Max und Where S...
Ich entwickle derzeit ein neues App-Projekt. Dies...
1. JDK installieren 1. Deinstallieren Sie die alt...
MySQL 5.7 und höhere Versionen ermöglichen die di...
--1. Erstellen Sie eine neue Gruppe und einen neu...