Ich weiß, Windows verwendet keine UNIX-Sockets, während Mac OS dies tut. Bis zu diesem Zeitpunkt war meine Software plattformübergreifend ohne Codeänderungen. Aber jetzt möchte ich, dass es etwas Netzwerkkommunikation macht. Ich kenne POSIX-Sockets, aber ich weiß nichts über die von Windows. Das Ziel ist die Implementierung eines einfachen plattformübergreifenden Socket-Servers.
Könnten Sie mir bitte die Unterschiede zwischen POSIX- und Winsock-Sockets erklären und wie ich beim Schreiben von plattformübergreifendem Netzwerkcode vorgehen kann?
WinSock versus POSIX-Sockets
WinSock und Posix Steckdosen funktionieren auf ähnliche Weise – hauptsächlich weil Windows-Sockets basierten ursprünglich auf Code von BSD:
Obwohl diese proprietären BSD-Derivate in den 1990er Jahren weitgehend durch die Systeme UNIX System V Release 4 und OSF / 1 ersetzt wurden (die beide BSD-Code enthielten und die Grundlage anderer moderner Unix-Systeme bilden), boten spätere BSD-Versionen eine Grundlage für mehrere offene Source-Entwicklungsprojekte, zB FreeBSD, OpenBSD, NetBSD, Darwin oder PC-BSD, die im Gange sind. Diese wiederum sind ganz oder teilweise in moderne proprietäre Betriebssysteme eingeflossen, z den TCP/IP-Netzwerkcode (nur IPv4) in Microsoft Windows und die meisten der Grundlagen von Apples OS X und iOS.
Es gibt jedoch ein paar Dinge, die Sie anders handhaben müssen, wenn Sie “socket-library-agnostic” Code schreiben möchten.
Hinweis: Die folgenden Beispiele wurden mit Code::Blocks und GCC unter Windows XP (x86) und Debian Testing (AMD64) getestet.
Die Header- und lib-Dateien sind unterschiedlich
Je nachdem, ob Sie Windows verwenden oder nicht, müssen Sie unterschiedliche Header-Dateien einfügen:
#ifdef _WIN32
/* See http://stackoverflow.com/questions/12765743/getaddrinfo-on-win32 */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501 /* Windows XP. */
#endif
#include <winsock2.h>
#include <Ws2tcpip.h>
#else
/* Assume that any non-Windows platform uses POSIX-style sockets instead. */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h> /* Needed for getaddrinfo() and freeaddrinfo() */
#include <unistd.h> /* Needed for close() */
#endif
Sie müssen auch mit verknüpfen Ws2_32
lib-Datei unter Windows.
WinSock erfordert Initialisierung und Bereinigung.
Die folgenden Funktionen veranschaulichen, wie Sie WinSock v1.1 initialisieren und anschließend bereinigen können:
int sockInit(void)
{
#ifdef _WIN32
WSADATA wsa_data;
return WSAStartup(MAKEWORD(1,1), &wsa_data);
#else
return 0;
#endif
}
int sockQuit(void)
{
#ifdef _WIN32
return WSACleanup();
#else
return 0;
#endif
}
Socket-Handles sind auf Winsock UNSIGNED
Für Sockets im POSIX-Stil können Sie einfach verwenden int
zum Aufbewahren eines Sockelgriffs. Ungültige Sockets werden durch einen negativen Wert angezeigt.
Jedoch, WinSock-Sockets sind UNSIGNED Integermit einer speziellen Konstante (INVALID_SOCKET
) anstelle von negativen Zahlen verwendet.
Sie können die Unterschiede durch abstrahieren typedef
ing SOCKET als int
auf POSIX und das Verstecken der Überprüfung “gültiger Socket” hinter einem Makro oder einer Funktion.
Steckdosen werden unterschiedlich geschlossen
Die folgende Funktion veranschaulicht die Unterschiede:
/* Note: For POSIX, typedef SOCKET as an int. */
int sockClose(SOCKET sock)
{
int status = 0;
#ifdef _WIN32
status = shutdown(sock, SD_BOTH);
if (status == 0) { status = closesocket(sock); }
#else
status = shutdown(sock, SHUT_RDWR);
if (status == 0) { status = close(sock); }
#endif
return status;
}
Im Allgemeinen sind sie sich jedoch ziemlich ähnlich.
Wenn Sie sich an “gängige” Funktionen halten (wie z send()
oder recv()
) und vermeiden Sie plattformspezifische Dinge (wie z WSAWaitForMultipleEvents()
) Dann sollte es dir gut gehen.
Kann ich auch empfehlen plibsys Bibliothek: funktioniert sowohl auf Windows- als auch auf UNIX-Systemen (siehe die vollständige Liste auf der Projektseite) mit verschiedenen Compilern. Unterstützt IPv4 und IPv6. Es hat die Tests, wo Sie die Anwendungsbeispiele sehen können. Die Bibliothek selbst ist leicht und tragbar.
Es gibt viele Bibliotheken und Toolkits, die plattformübergreifende Sockets unterstützen, je nachdem, was Sie tun, können Sie verwenden (um nur einige zu nennen):
- openssl
- Apache portable Laufzeitumgebung
- libtcl
Wenn Sie nicht von einer externen Bibliothek abhängig sein möchten, haben alle oben genannten Pakete ziemlich freizügige Lizenzen, sodass Sie ihren Code als Referenz verwenden können.
Die regulären Sockets (die in der AF_INET-Adressfamilie), die Sie zum Erstellen eines Socket-Servers benötigen, werden auf allen Plattformen gleichermaßen unterstützt.
Verwechseln Sie sie nicht mit Unix-Sockets (die in der AF_UNIX-Adressfamilie) – solche Sockets sind sehr spezifisch für eine Unix-Welt und werden für sehr spezifische Ziele verwendet. Sie würden sie niemals für eine einfache Socket-Server-Anwendung benötigen.
Es geht über reine Sockets hinaus, aber ich finde 0mq (ZeroMq) sehr interessant.
– naja
19. Januar 2015 um 15:24 Uhr
Normalerweise nehme ich das POSIX-Programm und kompiliere es mit gcc unter Cygwin und verteile es dann so 😉 Zusätzlicher Bonus: Es macht mein Leben unter Windows viel einfacher.
– Karl Kubat
19. Januar 2015 um 15:25 Uhr
Leider (?) Fragen, die Empfehlungen stellen, sind hier ausdrücklich nicht zum Thema. Eine Lösung besteht jedoch darin, entweder Cygwin (wenn Sie eine andere Unix-ähnliche Infrastruktur benötigen) oder Mingw (wenn Sie keine “gefälschte Unix” -Umgebung für Ihr Programm benötigen, nur die C-Bibliotheken / APIs sind ausreichend) zum direkten Erstellen zu verwenden Ihren Unix/Linux-Quellcode.
– Hyde
19. Januar 2015 um 15:28 Uhr
stackoverflow.com/questions/2952733/…
– Matte
19. Januar 2015 um 15:30 Uhr
Dies ist die Art von Frage, die sehr nützlich war, tut mir leid, dass sie geschlossen wurde
– Harald Scheirich
22. Oktober 2019 um 16:47 Uhr