Es ist schwierig, einen Server in der Sprache c einzurichten. Der Zweck dieses Artikels ist es, Neulingen und Personen, die noch nie einen Server geschrieben haben, zu ermöglichen, ihn vorerst zu verschieben und einige Fragen zu beantworten. Wenn Sie einen Server erstellen müssen und gerade arbeiten, können Sie Zeit sparen, indem Sie den folgenden Code kopieren und gemäß Ihren Geschäftsspezifikationen neu schreiben. Diesmal wird es in UDP sehr einfach sein. Ich denke, dies reicht möglicherweise nicht für die tatsächlichen Anforderungen. Es ist jedoch einfacher, sich vorwärts zu bewegen, wenn Sie verbunden sind, als wenn Sie überhaupt keine Hände oder Beine haben. Spielen Sie von hier aus mit dem Code, der Ihren Anforderungen entspricht. In diesem Artikel gibt es keine Erklärung dafür, was UDP ist. Es gibt so viele Erklärungen im Internet, dass sie faul sind. Bitte benutzen Sie diese. Für Bücher ist "Computer Network 5th Edition" gut, aber der Preis und die Dicke sind so ...
Ich werde die Umgebung, die ich vorerst ausprobiert habe, einsetzen, aber ich denke, dass sie mit relativ neuem Linux funktionieren wird.
Ubuntu 18.04.2 LTS
gcc 7.4.0
Aus Sicht der Implementierung kann UDP als einfaches TCP betrachtet werden.
Als einfacher Server
--Daten werden von localhost`` 9002
empfangen
Derzeit sieht der Code, der beim Kopieren und Einfügen funktioniert, folgendermaßen aus.
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main ()
{
//1.Erstellen Sie eine Empfangsadresse
struct addrinfo hints;
memset (&hints, 0, sizeof (hints));
hints.ai_socktype = SOCK_DGRAM;
struct addrinfo *bind_address;
getaddrinfo ("localhost", "9002", &hints, &bind_address);
//2.Erstellen Sie einen Socket
int socket_listen;
socket_listen = socket (bind_address->ai_family,
bind_address->ai_socktype,
bind_address->ai_protocol);
if (socket_listen < 0)
{
fprintf (stderr, "socket() failed. (%d)\n", errno);
return 1;
}
//3.Binden Sie die lokale Adresse an den Socket
if (bind (socket_listen, bind_address->ai_addr, bind_address->ai_addrlen))
{
fprintf (stderr, "bind() failed. (%d)\n", errno);
return 1;
}
freeaddrinfo (bind_address);
//4.Warten Sie auf die Clientverbindung
while (1)
{
struct sockaddr_storage client_address;
socklen_t client_len = sizeof (client_address);
char read[4096];
memset(read, 0, sizeof(read));
int bytes_received = recvfrom (socket_listen, read, 4096, 0,
(struct sockaddr *) &client_address,
&client_len);
if (bytes_received < 1)
{
fprintf (stderr, "connection closed. (%d)\n", errno);
return 1;
}
printf("receiving: %s", read);
}
//5.Steckdose schließen
close(socket_listen);
printf ("Finished.\n");
return 0;
}
Es gibt verschiedene Möglichkeiten, eine Verbindungsstruktur aufzubauen.
Dieses Mal habe ich es nach der dritten Methode gebaut.
Es gibt drei Aufgaben, um die Funktion "getaddrinfo" zu verwenden.
Die addrinfo Struktur
in 3 setzt normalerweise ip4 oder ip6, TCP oder UDP.
Wenn ip 0 ist, wird es zu ip4.
SOCK_DGRAM ist ein
Datagramm, und wenn es gesetzt ist, wird es UDP.
Ich habe es diesmal nicht verwendet, aber der Rückgabewert der Funktion "getaddrinfo" ist errno. Wenn Sie es also richtig machen, sollten Sie es erhalten.
Dies ist derjenige, der mit solch einer vollständigen Gewohnheit schreibt, egal wer es tut. Ein Socket ist ein Kommunikationsterminal (in einem Programm), und das Betriebssystem sendet und empfängt über den Socket. Die "Socket-Funktion" erstellt einen Socket-Deskriptor. Ein Socket-Deskriptor ist eine Art Dateideskriptor. Ein Dateideskriptor ist eine eindeutige Nummer, mit der das Betriebssystem Dateien verarbeiten kann. Linux behandelt verschiedene Dinge als Dateien. Textdateien, Geräte (z. B. USB-Speicher) usw. In der Lage sein, wie Dateien im Netzwerk zu lesen und zu schreiben Dies ist die Rolle des Socket-Deskriptors. Der Rückgabewert der Socket-Funktion ist der Socket-Deskriptor.
Dies ist auch eine Gewohnheit. Verknüpfen Sie die von der Bindefunktion empfangene Adresse mit dem Socket. Jetzt sind Sie bereit zu empfangen.
Der wichtigste Prozess.
Ich bin sicher, wir werden hier in diesem Chan verschiedene Dinge tun.
Normalerweise wird der Server nicht gelöscht, sodass er eine unbegrenzte Schleife aufweist.
Verwenden Sie zum Empfangen die Funktion "recvfrom".
Die Funktion "recvfrom" empfängt die Quellinformationen.
Die sockaddr_storage Struktur
ist eine Struktur, die entweder durch ip4 oder ip6 dargestellt werden kann.
Wie Speicher und Threads lecken Sockets, sodass Sie sie öffnen müssen. Die Funktion "Schließen" wird verwendet, um die Datei zu schließen. Da der Socket auch als Datei behandelt werden kann, kann er mit derselben Schließfunktion wie die Datei geöffnet werden.
Ich habe das Gefühl, ich brauche es nicht. Ich lese die Verbindungsfunktion, obwohl es UDP ist. Tatsächlich können Sie die Verbindungsfunktion in UDP verwenden. Sie können auch mit der Verbindungsfunktion auf dem Server schreiben. Wenn Sie die Verbindungsfunktion in UDP verwenden, verhält sie sich anders als in TCP. Die Erklärung hier ist ... gut.
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_DGRAM;
struct addrinfo *peer_addr;
if(getaddrinfo("localhost","9002",&hints, &peer_addr))
{
fprintf(stderr, "getaddrinfo() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
char addrbuf[100];
char servbuf[100];
getnameinfo(peer_addr->ai_addr, peer_addr->ai_addrlen, addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST);
printf("%s %s\n", addrbuf, servbuf);
puts("Creating socket");
int socket_peer;
socket_peer = socket(peer_addr->ai_family, peer_addr->ai_socktype, peer_addr->ai_protocol);
if(!ISVALIDSOCKET(socket_peer))
{
fprintf(stderr, "socket() failed. (%d)\n", GETSOCKETERRNO());
return 1;
}
if(connect(socket_peer,peer_addr->ai_addr, peer_addr->ai_addrlen))
{
fprintf(stderr,"connect() failed. (%d).\n", GETSOCKETERRNO());
return 1;
}
freeaddrinfo(peer_addr);
puts("Connected");
while(1)
{
{
char read[4096];
if(!fgets(read, 4096, stdin)) break;
int bytes = send(socket_peer, read, strlen(read), 0);
printf("send %d bytes\n", bytes);
}
}
puts("Closing socket");
CLOSESOCKET(socket_peer);
return 0;
}