Winsock Send Daten Binär Optionen


PHP Socket Programmierung Tutorial Php und tcpip Steckdosen Dies ist eine schnelle guidetutorial zu lernen Socket-Programmierung in PHP. Socket-Programmierung PHP ist sehr ähnlich zu C. Die meisten Funktionen sind ähnlich in Namen, Parameter und Ausgabe. Im Gegensatz zu C, Socket-Programme in PHP geschrieben würde die gleiche Weise auf alle os, die PHP installiert hat laufen. So braucht der Code keine plattformspezifischen Änderungen (meistens). Um die Grundlagen zusammenzufassen, sind Sockets die grundlegenden Dinge hinter jeder Art von Netzwerk-Kommunikation von Ihrem Computer durchgeführt. Zum Beispiel, wenn Sie google in Ihrem Web-Browser eingeben, öffnet es einen Socket und verbindet sich mit Google, um die Seite zu holen und es Ihnen zu zeigen. Gleiche mit jedem Chat-Client wie gtalk oder Skype. Jede Netzwerkkommunikation durchläuft eine Steckdose. Bevor Sie beginnen Dieses Tutorial geht davon aus, dass Sie bereits PHP kennen und auch wie man PHP-Skripte aus dem Kommando - Php-Scripts werden normalerweise aus dem Browser ausgeführt, indem sie sie in das Apache-Stammverzeichnis wie var setzen. Diese Kommandozeilenprogramme können jedoch aus jedem beliebigen Verzeichnis ausgeführt werden. Sie können auch von den Browsern laufen. So fangen wir mit sockets an. Erstellen einer Steckdose Diese erste Sache zu tun ist, erstellen Sie eine Steckdose. Die Socketcreate-Funktion macht dies. Hier ist ein Codebeispiel: Funktion socketcreate erstellt einen Socket und gibt einen Socket-Deskriptor zurück, der in anderen Netzwerkbefehlen verwendet werden kann. Der obige Code erzeugt einen Socket mit den folgenden Eigenschaften. Adresse Familie. AFINET (das ist IP Version 4) Typ. SOCKSTREAM (das bedeutet verbindungsorientiertes TCP-Protokoll) Protokoll. 0 oder IPPROTOIP Dies ist IP-Protokoll Wenn eine der Socket-Funktionen fehlschlägt, können die Fehlerinformationen mit den Funktionen socketlasterror und socketstrerror abgerufen werden. OK. So haben Sie eine Steckdose erfolgreich erstellt. Aber was als nächstes Als nächstes werden wir versuchen, eine Verbindung zu einem Server mit diesem Socket zu verbinden. Wir können eine Verbindung zu Google herstellen. Abgesehen von SOCKSTREAM Art von Sockets gibt es einen anderen Typ namens SOCKDGRAM, der das UDP-Protokoll anzeigt. Diese Steckdose ist eine Steckdose. In diesem Tutorial bleiben wir bei SOCKSTREAM oder TCP Sockets. Verbindung zu einem Server herstellen Wir verbinden uns mit einem Remote-Server an einer bestimmten Portnummer. Also brauchen wir 2 Dinge. IP-Adresse und Portnummer, um eine Verbindung herzustellen. Sie müssen also die IP-Adresse des entfernten Servers kennen, mit dem Sie sich verbinden. Hier haben wir die IP-Adresse von Google als Beispiel verwendet. Ein wenig später werden wir sehen, wie man die IP-Adresse eines bestimmten Domainnamens herausfindet. Das letzte, was benötigt wird, ist die Verbindungsfunktion. Es braucht eine Steckdose und eine Sockaddr-Struktur, um eine Verbindung herzustellen. Hier ist ein Codebeispiel. Führen Sie das Programm php varwwwsocket. php Socket erstellt Verbindung hergestellt Es schafft eine Steckdose und verbindet dann. Versuchen Sie die Verbindung zu einem Port, der sich von Port 80 unterscheidet, und Sie sollten nicht in der Lage sein, eine Verbindung herzustellen, die angibt, dass der Port nicht für die Verbindung geöffnet ist. Diese Logik kann verwendet werden, um einen Port-Scanner zu erstellen. OK, also sind wir jetzt verbunden. Lass uns das nächste machen Senden von Daten an den entfernten Server. Das Konzept der Anschlüsse gilt für SOCKSTREAMTCP-Steckdosen. Verbindung bedeutet einen zuverlässigen Datenstrom, so dass es mehrere solche Ströme geben kann, die jeweils eine eigene Kommunikation haben. Denken Sie an diese als eine Pipe, die nicht durch andere Daten gestört wird. Andere Steckdosen wie UDP. ICMP ARP hat kein Konzept der Verbindung. Diese sind nicht verbindungsbasierte Kommunikation. Was bedeutet, dass Sie Pakete von irgendjemandem und jedem senden oder empfangen. Senden von Daten Funktion send sendet einfach Daten. Es braucht der Socket-Deskriptor. Die zu sendenden Daten und deren Größe. Hier ist ein sehr einfaches Beispiel für das Senden von einigen Daten zu google ip: Im obigen Beispiel. Wir verbinden uns zunächst mit einer IP-Adresse und senden dann die String-Nachricht GET HTTP1.1rnrn dazu. Die Nachricht ist eigentlich ein http-Befehl, um die Hauptseite einer Website zu holen. Jetzt haben wir einige Daten gesendet. Seine Zeit, eine Antwort vom Server zu erhalten. Also machen wir's. Beim Senden von Daten an eine Steckdose schreibst du grundsätzlich Daten an diesen Sockel. Dies ähnelt dem Schreiben von Daten in eine Datei. So können Sie auch die Schreibfunktion verwenden, um Daten an einen Socket zu senden. Später in diesem Tutorial verwenden wir Schreibfunktion, um Daten zu senden. Empfangen von Daten Funktion recv wird verwendet, um Daten auf einem Socket zu empfangen. Im folgenden Beispiel werden wir die gleiche Nachricht wie das letzte Beispiel senden und eine Antwort vom Server erhalten. Hier ist die Ausgabe des obigen Codes: Wir können sehen, welche Antwort vom Server gesendet wurde. Es sieht so aus wie html, gut es ist html. Google antwortete mit dem Inhalt der von uns angeforderten Seite. Ganz einfach Nun, da wir unsere Antwort erhalten haben, ist es an der Zeit, die Steckdose zu schließen. Schließen Sie die Steckdose Funktion socketclose wird verwendet, um die Steckdose zu schließen. Lets Revise So im obigen Beispiel haben wir gelernt, wie man: 1. Erstellen Sie einen Socket 2. Verbinden Sie mit dem Remote-Server 3. Senden Sie einige Daten 4. Erhalten Sie eine Antwort Es ist nützlich zu wissen, dass Ihr Web-Browser auch das Gleiche tut, wenn Sie Google öffnen Diese Art von Socket-Aktivität repräsentiert einen CLIENT. Ein Client ist ein System, das eine Verbindung zu einem entfernten System herstellt, um Daten abzurufen. Die andere Art von Socket-Aktivität heißt SERVER. Ein Server ist ein System, das Sockets verwendet, um eingehende Verbindungen zu empfangen und ihnen Daten zur Verfügung zu stellen. Es ist genau das Gegenteil von Client. So ist Google ein Server und dein Webbrowser ist ein Client. Oder mehr technisch Google ist ein HTTP Server und Ihr Webbrowser ist ein HTTP Client. Jetzt ist es Zeit, einige Server-Aufgaben mit Sockets zu tun. Aber bevor wir vorankommen, gibt es ein paar Nebenthemen, die abgedeckt werden sollen. IP-Adresse einer hostnamedomain erhalten Bei der Verbindung zu einem entfernten Host. Es ist notwendig, seine IP-Adresse zu haben. Funktion gethostbyname wird hierfür verwendet. Es nimmt den Domain-Namen als Parameter und gibt die IP-Adresse zurück. So kann der obige Code verwendet werden, um die IP-Adresse eines beliebigen Domainnamens zu finden. Dann kann die IP-Adresse verwendet werden, um eine Verbindung mit einem Socket zu machen. Server-Programmierung OK jetzt auf Server-Sachen. Server haben grundsätzlich folgendes: 1. Öffnen Sie eine Steckdose 2. Binden Sie an eine Adresse (und einen Port). 3. Hören Sie auf eingehende Verbindungen. 4. Verbindungen annehmen 5. ReadSend Wir haben bereits gelernt, wie man einen Socket öffnet. Also das nächste Ding wäre, es zu binden. Binden Sie eine Steckdose Funktion Bindung kann verwendet werden, um eine Steckdose an eine bestimmte Adresse und Port zu binden. Es braucht eine Sockaddrin-Struktur ähnlich wie die Connect-Funktion. Jetzt ist die Bindung fertig, ihre Zeit, um die Steckdose zu hören, um Verbindungen zu machen. Wir binden einen Sockel an eine bestimmte IP-Adresse und eine bestimmte Portnummer. Dabei stellen wir sicher, dass alle eingehenden Daten, die auf diese Portnummer gerichtet sind, bei dieser Anwendung eingegangen sind. Dies macht es offensichtlich, dass man nicht 2 Steckdosen an denselben Port gebunden haben kann. Es gibt Ausnahmen von dieser Regel, aber wir werden das in einem anderen Artikel untersuchen. Hören Sie nach Verbindungen Nach dem Binden eines Sockets an einen Port das nächste, was wir tun müssen, ist auf Verbindungen zu hören. Dazu müssen wir die Steckdose in den Hörmodus stellen. Funktion socketlisten wird verwendet, um die Steckdose in den Hörmodus zu versetzen. Fügen Sie einfach die folgende Zeile nach binden hinzu. Der zweite Parameter der Funktion socketlisten heißt Rückstand. Es steuert die Anzahl der eingehenden Verbindungen, die gehalten werden, wenn das Programm bereits besetzt ist. Mit der Angabe von 10 bedeutet dies, dass, wenn bereits 10 Verbindungen warten, um verarbeitet zu werden, dann die 11. Anschlussanforderung abgelehnt wird. Dies wird nach der Überprüfung von socketaccept deutlicher. Jetzt kommt der Hauptteil der Annahme neuer Verbindungen. Annahme der Verbindung Funktion socketaccept wird dafür verwendet. Führen Sie das Programm aus. Es sollte php zeigen varwwwserver. php Socket erstellt Socket binden OK Socket hören OK Warten auf eingehende Verbindungen. Also jetzt dieses Programm wartet auf eingehende Verbindungen auf Port 5000. Dont schließen dieses Programm. Lass es laufen Jetzt kann sich ein Client an diesen Port anschließen. Wir werden den telnet-Client zum Testen verwenden. Öffnen Sie ein Terminal und geben Sie telnet localhost 5000 Es wird sofort telnet localhost 5000 Trying 127.0.0.1. Verbunden mit localhost. Escape-Charakter ist. Verbindung durch fremde Gastgeber geschlossen Und die Server-Ausgabe zeigt Client 127.0.0.1. 36689 ist jetzt mit uns verbunden. So können wir sehen, dass der Client mit dem Server verbunden ist. Versuchen Sie die oben genannten Schritte, bis Sie es funktionieren perfekt. Die Funktion socketgetpeername wird verwendet, um Details über den Client zu erhalten, der über einen bestimmten Socket mit dem Server verbunden ist. Wir haben eine eingehende Verbindung angenommen, aber sofort geschlossen. Das war nicht sehr produktiv. Es gibt viele Dinge, die nach einer eingehenden Verbindung hergestellt werden können. Danach wurde die Verbindung zum Zweck der Kommunikation hergestellt. So können wir auf den Kunden antworten. Funktion socketwrite kann verwendet werden, um etwas in den Socket der eingehenden Verbindung zu schreiben und der Client sollte es sehen. Hier ist ein Beispiel: Führen Sie den obigen Code in 1 Terminal. Und verbinden Sie mit diesem Server mit telnet von einem anderen Terminal und Sie sollten dies sehen: So hat der Client (telnet) eine Antwort vom Server erhalten. Wir können sehen, dass die Verbindung sofort danach geschlossen wird, nur weil das Server-Programm nach dem Annehmen und Senden der Antwort endet. Ein Server wie Google ist immer bereit, eingehende Verbindungen zu akzeptieren. Es bedeutet, dass ein Server die ganze Zeit laufen soll. Danach soll ein Server dienen. Also müssen wir unseren Server RUNNING non-stop halten. Der einfachste Weg, dies zu tun ist, um die akzeptieren in einer Schleife, so dass es eingehende Verbindungen die ganze Zeit empfangen können. Live Server So wird ein Live-Server immer am Leben sein. Lets Code dies bis wir havent viel gemacht dort. Setzen Sie einfach das Socketaccept in eine Schleife. Führen Sie nun das Server-Programm in 1 Terminal aus. Und 3 weitere Terminals öffnen. Von jedem der 3-Terminal tippe ein Telnet zum Server-Port. Jeder der telnet-Terminal würde zeigen: telnet localhost 5000 Trying 127.0.0.1. Verbunden mit localhost. Escape-Charakter ist. Glücklich ok Glücklich Verbindung von fremden Gastgeber geschlossen Und das Server-Terminal würde zeigen, php varwwwserver. php Socket erstellt Socket binden OK Socket hören OK Warten auf eingehende Verbindungen. Client 127.0.0.1. 37119 ist jetzt mit uns verbunden. Client 127.0.0.1. 37122 ist jetzt mit uns verbunden. Client 127.0.0.1. 37123 ist jetzt mit uns verbunden. Also jetzt läuft der server nonstop und die telnet terminals sind auch nonstop verbunden. Schließen Sie nun das Server-Programm. Alle Telnet-Terminals würden die Verbindung von einem ausländischen Host schließen lassen. Gut soweit. Aber es gibt noch keine effektive Kommunikation zwischen dem Server und dem Client. Das Server-Programm akzeptiert Verbindungen in einer Schleife und schickt ihnen einfach eine Antwort, danach tut es nichts mit ihnen. Auch ist es nicht möglich, mehr als 1 Verbindung zu einem Zeitpunkt zu behandeln. So jetzt seine Zeit, um die Verbindungen zu behandeln. Und verarbeiten mehrere Verbindungen zusammen. Handhabung von Verbindungen Um jede Verbindung zu behandeln, benötigen wir einen separaten Handhabungscode, der zusammen mit dem Hauptserver ausgeführt wird, der Verbindungen akzeptiert. Eine Möglichkeit, dies zu erreichen, ist die Verwendung von Threads. Das Haupt-Server-Programm akzeptiert eine Verbindung und erstellt einen neuen Thread, um die Kommunikation für die Verbindung zu behandeln, und dann geht der Server zurück, um mehr Verbindungen zu akzeptieren. PHP unterstützt das Threading nicht direkt. Eine andere Methode ist, die Auswahlfunktion zu verwenden. Die Auswahlfunktion grundsätzlich abfragt oder beobachtet eine Reihe von Sockets für bestimmte Ereignisse wie wenn es lesbar oder beschreibbar oder ein Problem oder nicht etc. So kann die Auswahlfunktion verwendet werden, um mehrere Clients zu überwachen und zu überprüfen, welcher Client eine Nachricht gesendet hat. Führen Sie den oben genannten Server aus und öffnen Sie 3 Terminals wie vorher. Jetzt wird der Server einen Thread für jeden Client, der mit ihm verbunden ist, erstellen. Die Telnet-Terminals würden zeigen: Das Server-Terminal könnte so aussehen. Der obige Verbindungs-Handler nimmt einige Eingaben vom Client und antwortet mit demselben zurück. Einfach hier ist, wie die telnet-Ausgabe aussehen könnte So jetzt haben wir einen Server, der kommunikativ ist. Das ist jetzt nützlich Fazit Inzwischen musst du die Grundlagen der Socket-Programmierung in PHP gelernt haben. Sie können versuchen, einige Experimente wie das Schreiben eines Chat-Client oder etwas ähnliches. Wenn Sie denken, dass das Tutorial braucht einige Addons oder Verbesserungen oder eine der Code-Snippets oben nicht funktionieren dann fühlen Sie sich frei, um einen Kommentar unten zu machen, so dass es behoben wird. Zuletzt aktualisiert am. 26. März 2013Senden von Binärdaten über UDP-Protokoll (Winsock) Ich mache ein Client-Programm, das Binärdaten benötigt, die über das UDP-Protokoll an den Server gesendet werden sollen. (Ich benutze die Winsock-Kontrolle) Ich habe den folgenden Code verwendet. Dim ByteX als Byte Dim X als Long Dim FileX als Interger Winsock3.LocalPort 10000 Winsock3.RemoteHost 211.233.70.51 Winsock3.RemotePort 9500 FileX FreeFile Öffnen Sie App. Path udp1.dat für Binary als FileX X 1 Do bis X FileLen (App. Path udp1.dat) 1 Erhalten Sie FileX. X, ByteX Winsock3.SendData ByteX X X 1 Loop Schließen FileX Wenn ich Daten auf diese Weise sende, sendet es 52 Pakete mit 1 Byte anstelle von 1 Paket mit 52 Bytes. Dieser Code funktioniert ordnungsgemäß für das TCP-Protokoll, aber UDP funktioniert nicht das gleiche. Wie kann ich binäre Daten mit dem UDP-Protokoll senden, das nur 1 Paket von Daten sendet Ich mache ein Client-Programm, das Binärdaten benötigt, um über das UDP-Protokoll an den Server gesendet zu werden. (Ich benutze die Winsock-Kontrolle):: Ich habe den folgenden Code verwendet. :: Dim ByteX als Byte: Dim X als Long: Dim FileX als Interger:: Winsock3.LocalPort 10000: Winsock3.RemoteHost 211.233.70.51: Winsock3.RemotePort 9500:: FileX FreeFile: Öffnen Sie App. Path udp1.dat für Binary als FileX : X 1: Do bis X FileLen (App. Path udp1.dat) 1: FileX erhalten. X, ByteX: Winsock3.SendData ByteX: X X 1: Loop: Schließen FileX:: Wenn ich Daten auf diese Weise sende, sendet es 52 Pakete mit 1 Byte anstelle von 1 Paket mit 52 Bytes. Dieser Code funktioniert ordnungsgemäß für das TCP-Protokoll, aber UDP funktioniert nicht das gleiche. Wie kann ich binäre Daten mit dem UDP-Protokoll senden, das nur 1 Paket von Daten senden wird: Hallo Versuche dieses Winsock3.Protocol sckUDPProtocol Winsock hat sckTCPProtocol standardmäßig .. purpleDont das Leben zu ernst nehmen sowieso Sie nicht entkommen lebendig aus itpurplesending binäre Daten mit winsock Im Entschuldigung, sagst du, dass ich Datagram anstelle von Stream Sockets verwenden muss, um diese Arbeit zu haben, die ich SOCKSTREAM gerade nutze, und ich würde es lieber damit bleiben. Gibt es eine Möglichkeit, dies zu bekommen, um die 0x00 akzeptieren und akzeptieren Daten nach ihm, während immer noch Stream-Sockets. Nochmals vielen Dank für eure Hilfe. Mikyu Hmm, das ist seltsam. Ich dachte, das SOCKDGRAM-Argument sollte binäre Daten angeben, im Gegensatz zu SOCKSTREAM. : Der recv sollte in jedem Fall über irgendwelche Nullen lesen. : Sind Sie sicher, dass Sie die Daten nicht in einem String-Datentyp erfassen, den Sie ausdrucken oder in eine Datei schreiben oder etwas mit einer der Str-Routinen: Ich meine, sind Sie sicher, dass Sie die empfangenen Daten korrekt anzeigen Es tut mir leid, sagen Sie, dass ich Datagram anstelle von Stream Sockets verwenden muss, um diese Arbeit zu haben, die ich SOCKSTREAM gerade nutze, und ich würde es lieber damit bleiben. Gibt es eine Möglichkeit, dies zu bekommen, um die 0x00 akzeptieren und akzeptieren Daten nach ihm, während immer noch Stream-Sockets. Nochmals vielen Dank für eure Hilfe. : Mikyu:. Hmm, das ist seltsam. Ich dachte, das SOCKDGRAM-Argument sollte binäre Daten angeben, im Gegensatz zu SOCKSTREAM. . Der Recv sollte in diesem Fall über irgendwelche Nullen hinauslesen. . Sind Sie sicher, dass Sie die Daten nicht in einem String-Datentyp erfassen, den Sie ausdrucken oder in eine Datei schreiben oder etwas mit einer der Str-Routinen. Ich meine, sind Sie sicher, dass Sie die empfangenen Daten korrekt anzeigen: SOCKDGRAM bedeutet nicht binäre Daten. Es bedeutet, dass Sie UDP-Protokoll verwenden möchten, um Daten zu senden und Daten werden in Datagrammen gesendet. SOCKSTREAM bedeutet, dass Sie TCP-Protokoll verwenden und Daten als Stream senden möchten. Socket kümmert sich nicht, welche Art von Daten Sie senden. Alles, was Sie brauchen, ist Zeiger auf Puffer, der die Daten und die Länge dieses Puffers enthält. Zero inside Daten bedeutet nichts, es ist einfach Null. Daten werden nicht durch Null beendet, da C-Strings sind. Socket kümmert sich nicht um den Inhalt der Daten. Ich glaube, es ist etwas falsch mit Ihnen erhalten Code. Vielleicht machst du null als terminator da, was sehr schlecht ist Wenn du Postleitzahlen haben könntest, der hier Daten empfängt, könnte ich versuchen, herauszufinden, was mit ihm falsch ist. Hier ist der Code, den ich benutze. Wieder, ich bin neu bei winsock so bitte bei mir zu tragen. Danke Code int Server (void) unsigned char recmsg3072 SOCKET Serverfd, Clientfd hören auf Sockfd, neue Verbindung auf newfd SOCKADDRIN serveraddr SOCKADDRIN clientaddr int len ​​int j int msgsize 0 char Frage WSADATA wsadata unsigned kurz verrequest FILE mike LINGER LingVar verrequest MAKEWORD (2,2 ) () () () () () () () () () () () () () () () () () () () (), (), Wenn Sie eine Setzer-SIDS - LingvoVerl. SpieleVerweiterungSprache (svdl) SvensoFreundlerner_Schneeflamme (fernseher).Sinport Htons (SERVERPORT) serveraddr. sinaddr. saddr htonl (INADDRANY) memset (amp (serveraddr. sinzero),, 8) if (bind (serverfd, (struct sockaddr) ampserveraddr, sizeof (serveraddr)) -1) perror (SERVER SIDE: kann nicht Port beenden) exit (1) if (listen (serverfd, PACKETQUEUE) -1) perror (SERVER SIDE: kann nicht auf Socket hören) exit (1) memset (recmsg, 0x0, 3072) while (1) printf (Do Du möchtest weitergehen (YN)) Frage getchar () if (Frage) Frage getchar () if (Frage N Frage n) return 0 printf (SERVER SIDE: Warten auf Daten auf Port) len sizeof (clientaddr) clientfd accept (serverfd, (SERVE SITE: Empfangene Verbindung von: s, Inetntoa (clientaddr. sinaddr)) msgsize readline (recmsg, clientfd, Clientaddr) if (msgsize ERROR) printf (SERVER SIDE: konnte die Nachricht nicht lesen) coutltltth ist die Nachricht Größe: ltltmsgsizeltltendl fwrite (recmsg, sizeof (short int), 10, mike) für (j0 jlt10 j) printf (- c, recmsgj () Mit (WSACleanup () -1) perror (Problem mit WSACLEANUP) exit (1) int readline (unsigned char buf, SOCKET sd, SOCKADDRIN clientaddr) char segMAXDATA int offset 0 int res 1 int cliLen memset (seg, 0x0, MAXDATA) cliLen sizeof (clientaddr) while ((res recvfrom (sd, seg, MAXDATA, 0, (struct sockaddr) ampclientaddr, ampcliLen)) SOCKETERROR) Wenn (resEOFresWSAECONNRESETresWSAECONNABORTED) 0other side terminated conn printf (Client terminated connection) Rückkehr versetzen Memcpy (bufoffset, seg, res) Offset res memset (seg, 0x0, MAXDATA) return ERROR code: SOCKDGRAM bedeutet nicht binäre Daten. Es bedeutet, dass Sie UDP-Protokoll verwenden möchten, um Daten zu senden und Daten werden in Datagrammen gesendet. SOCKSTREAM bedeutet, dass Sie TCP-Protokoll verwenden und Daten als Stream senden möchten. :: Socket kümmert sich nicht, welche Art von Daten Sie senden. Alles, was Sie brauchen, ist Zeiger auf Puffer, der die Daten und die Länge dieses Puffers enthält. :: Null innerhalb der Daten bedeutet nichts, es ist einfach Null. Daten werden nicht durch Null beendet, da C-Strings sind. Socket kümmert sich nicht um den Inhalt der Daten. :: Ich glaube, es ist etwas falsch mit dir erhalten Code. Vielleicht machst du null als terminator da, was sehr schlecht ist Wenn du Postleitzahlen haben könntest, der hier Daten empfängt, könnte ich versuchen, herauszufinden, was mit ihm falsch ist. : Ein Intro zu Windows Socket Programmierung mit C Was haben wir in diesem Kapitel 1 Teil 4 Datenübertragung senden () und WSASend () WSASendDisconnect () Out-of-Band Daten recv () und WSARecv () WSARecvDisconnect () Stream Protocols Scatter () TCP ReceiverServer Mit select () Beispiel Datenübertragung send () und WSASend () WSASendDisconnect () Out-of-Band Daten recv () und WSARecv () Die Empfangsanfrage wird nur abgeschlossen Wenn eines der folgenden Ereignisse auftritt: Der vom Anrufer gelieferte Puffer ist voll voll. Die Verbindung wurde geschlossen. Die Anforderung wurde storniert oder ein Fehler aufgetreten. Beachten Sie, dass, wenn der zugrunde liegende Transport MSGWAITALL nicht unterstützt oder wenn sich der Socket in einem nicht blockierenden Modus befindet, wird dieser Aufruf mit WSAEOPNOTSUPP fehlschlagen. Auch wenn MSGWAITALL zusammen mit MSGOOB, MSGPEEK oder MSGPARTIAL angegeben wird, dann wird dieser Aufruf mit WSAEOPNOTSUPP fehlschlagen. Dieses Flag wird nicht auf Datagramm-Sockets oder nachrichtenorientierten CO-Sockets unterstützt. Natürlich gibt 0 keine Sonderaktionen an. MSGPEEK bewirkt, dass die Daten, die verfügbar sind, in den bereitgestellten Empfangspuffer kopiert werden. Aber diese Daten werden nicht aus dem Systempuffer entfernt. Die Anzahl der anhängigen Bytes wird ebenfalls zurückgegeben. Message peeking ist schlecht Nicht nur, dass es die Leistung beeinträchtigt, da Sie jetzt zwei Systemaufrufe machen müssen (eine, um zu sehen und eine ohne das MSGPEEK-Flag, um die Daten tatsächlich zu entfernen), aber es ist auch unter bestimmten Umständen unzuverlässig. Die zurückgegebenen Daten spiegeln möglicherweise nicht die gesamte verfügbare Menge wider. Auch beim Verlassen von Daten in den Systempuffern hat das System weniger Platz, um eingehende Daten zu enthalten. Als Ergebnis reduziert das System die TCP-Fenstergröße für alle Absender. Dies verhindert, dass Ihre Anwendung den maximal möglichen Durchsatz erreicht. Das Beste, was zu tun ist, ist, alle Daten zu kopieren, die Sie in Ihren eigenen Puffer kopieren und dort manipulieren können. Es gibt einige Überlegungen bei der Verwendung von recv () auf einem Message - oder Datagramm-basierten Socket wie UDP, was wir später beschreiben werden. Wenn die Daten anstehen, die größer sind als der mitgelieferte Puffer, wird der Puffer mit so vielen Daten gefüllt, wie er enthält. In diesem Fall erzeugt der recv () - Aufruf den Fehler WSAEMSGSIZE. Beachten Sie, dass der Message-Size-Fehler mit Message-orientierten Protokollen auftritt. Stream-Protokolle wie TCP-Puffer eingehende Daten und wird so viele Daten wie die Applikationsanforderungen zurückgeben, auch wenn die Anzahl anstehender Daten größer ist. Also, für Streaming-Protokolle werden Sie nicht auf den WSAEMSGSIZE-Fehler stoßen. Die Funktion WSARecv () fügt einige neue Funktionen über recv () hinzu, wie z. B. überlappende IO - und partielle Datagramm-Benachrichtigungen. Die Definition von WSARecv () lautet: Parameter s ist die angeschlossene Steckdose. Der zweite und der dritte Parameter sind die Puffer, um die Daten zu empfangen. Der Parameter lpBuffers ist ein Array von WSABUF-Strukturen und dwBufferCount gibt die Anzahl der WSABUF-Strukturen im Array an. Der Parameter lpNumberOfBytesReceived verweist auf die Anzahl der Bytes, die von diesem Aufruf empfangen werden, wenn der Empfangsvorgang sofort abgeschlossen ist. Der Parameter lpFlags kann einer der Werte MSGPEEK, MSGOOB oder MSGPARTIAL oder eine bitweise ODER-Kombination dieser Werte sein. Die MSGPARTIAL-Flagge hat mehrere verschiedene Bedeutungen, je nachdem, wo sie verwendet oder angetroffen wird. Für Message-orientierte Protokolle, die partielle Messaging (wie AppleTalk) unterstützen, wird dieses Flag auf die Rückkehr von WSARecv () gesetzt (wenn die gesamte Nachricht in diesem Aufruf wegen unzureichendem Pufferplatz nicht zurückgegeben werden konnte). In diesem Fall setzen die nachfolgenden WSARecv () - Aufrufe dieses Flag, bis die gesamte Nachricht zurückgegeben wird, wenn das MSGPARTIAL-Flag gelöscht wird. Wenn dieses Flag als Eingabeparameter übergeben wird, sollte der Empfangsvorgang abgeschlossen sein, sobald Daten verfügbar sind, auch wenn es nur ein Teil der gesamten Nachricht ist. Das MSGPARTIAL-Flag wird nur mit nachrichtenorientierten Protokollen verwendet, nicht mit Streaming. Darüber hinaus unterstützen nicht alle Protokolle Teilnachrichten. Der Protokolleintrag für jedes Protokoll enthält ein Flag, das angibt, ob es diese Funktion unterstützt. Die Parameter lpOverlapped und lpCompletionRoutine werden in überlappenden IO-Operationen verwendet, die in einem anderen Kapitel beschrieben werden. Es gibt eine weitere spezialisierte Empfangsfunktion, die Sie beachten sollten: WSARecvDisconnect (). WSARecvDisconnect () Diese Funktion ist das Gegenteil von WSASendDisconnect () und ist wie folgt definiert: int WSARecvDisconnect (SOCKET s, LPWSABUF lpInboundDisconnectData) Wie die sendenden Gegenstücke sind die Parameter von WSASendDisconnect () der verbundene Socket-Handle und eine gültige WSABUF-Struktur mit dem Daten, die empfangen werden sollen. Die empfangenen Daten können nur Daten trennen, die von einem WSASendDisconnect () auf der anderen Seite gesendet werden. Es kann nicht verwendet werden, um normale Daten zu erhalten. Zusätzlich, sobald die Daten empfangen werden, deaktiviert diese Funktion den Empfang von der Gegenstelle, was gleichbedeutend ist, die Funktion shutdown () (die später beschrieben wird) mit SDRECEIVE aufzurufen. Stream-Protokolle Da die meisten verbindungsorientierten Kommunikation, wie TCP, Streaming-Protokolle ist, beschreibe sie kurz hier. Ein Streaming-Protokoll ist eines, das der Sender und der Empfänger aufteilen oder verschmelzen können Daten in kleinere oder größere Gruppen. Die folgende Abbildung beschreibt kurz den Fluss des TCP-Pakets zwischen Client - und Serverseiten. Die Hauptsache, mit irgendeiner Funktion bewusst zu sein, die Daten in einem Stream-Socket sendet oder empfängt, ist, dass Sie nicht garantiert sind, die Datenmenge zu lesen oder zu schreiben, die Sie anfordern. Lets sagen, Sie haben einen Zeichenpuffer mit 2048 Bytes Daten, die Sie mit der Sendefunktion senden möchten. Der Code, um dies zu senden ist: int nBytes 2048 Füllen Sie sendbuff mit 2048 Bytes von Daten Angenommen, s ist eine gültige, verbundene Stream-Socket ret send (s, sendbuff, nBytes, 0) Es ist möglich, dass send zurückkehren, um weniger als 2048 Bytes gesendet zu haben . Die ret-Variable wird auf die Anzahl der gesendeten Bytes gesetzt, da das System für jeden Socket eine bestimmte Menge an Pufferplatz zuteilt, um Daten zu senden und zu empfangen. Im Falle des Sendens von Daten halten die internen Puffer Daten, die gesendet werden sollen, bis die Daten auf dem Draht platziert werden können. Mehrere gemeinsame Situationen können dies verursachen. Zum Beispiel, einfach die Übertragung einer riesigen Menge an Daten wird dazu führen, dass diese Puffer schnell gefüllt werden. Auch für TCPIP gibt es das, was als Fenstergröße bekannt ist (Schiebefenster-Demo). Das empfangende Ende passt diese Fenstergröße an, um anzugeben, wieviel Daten sie empfangen können. Wenn der Empfänger mit Daten überflutet wird, kann er die Fenstergröße auf 0 setzen, um die ausstehenden Daten aufzuholen. Dies wird den Absender zwingen, zu stoppen, bis er eine neue Fenstergröße größer als 0 erhält. Im Falle unseres Sendeaufrufs könnte es Pufferplatz geben, um nur 1024 Bytes zu halten. In diesem Fall müssten Sie die restlichen 1024 Bytes erneut einreichen. Der folgende Code sorgt dafür, dass alle Ihre Bytes gesendet werden: int nBytes 2048, nLeft, idx Füllen Sie sendbuff mit 2048 Bytes Daten, während (nLeft gt 0) Angenommen, s ist eine gültige, verbundene Stream-Sockel Sachen wird ein wenig kompliziert, wenn Ihre Nachrichtengrößen variieren . Es ist notwendig, dein eigenes Protokoll aufzuerlegen, damit der Empfänger weiß, wie groß die bevorstehende Nachricht sein wird. Zum Beispiel sind die ersten vier Bytes, die an den Empfänger geschrieben werden, immer die Integer-Größe in Bytes der bevorstehenden Nachricht. Der Empfänger startet jedes Lesen, indem er die ersten vier Bytes betrachtet, sie in eine Ganzzahl umwandelt und bestimmt, wie viele zusätzliche Bytes diese Nachricht enthält. Scatter-Gather IO Scatter-Gather-Unterstützung ist ein Konzept, das ursprünglich in Berkeley Sockets mit den Funktionen recv und writev eingeführt wurde. Diese Funktion ist mit den Winsock 2 Funktionen WSARecv (), WSARecvFrom (), WSASend () und WSASendTo () verfügbar. Es ist besonders nützlich für Anwendungen, die Daten senden und empfangen, die auf eine ganz bestimmte Art formatiert sind. Zum Beispiel können Nachrichten von einem Client zu einem Server immer aus einem festen 32-Byte-Header bestehen, der eine Operation spezifiziert, gefolgt von einem 64-Byte-Datenblock und mit einem 16-Byte-Trailer abgeschlossen. In diesem Beispiel kann WSASend () mit einem Array von drei WSABUF-Strukturen aufgerufen werden, die jeweils den drei Nachrichtentypen entsprechen. Am empfangenden Ende wird WSARecv () mit drei WSABUF-Strukturen aufgerufen, die jeweils Datenpuffer von 32 Bytes, 64 Bytes und 16 Bytes enthalten. Bei der Verwendung von Stream-basierten Sockets behandeln Scatter-Gather-Operationen einfach die bereitgestellten Datenpuffer in den WSABUF-Strukturen als einen zusammenhängenden Puffer. Auch der Empfangsruf kann zurückkehren, bevor alle Puffer voll sind. Bei Message-basierten Sockets empfängt jeder Aufruf einer Empfangsoperation eine einzelne Nachricht bis zu der gelieferten Puffergröße. Wenn der Pufferplatz unzureichend ist, schlägt der Anruf mit WSAEMSGSIZE fehl und die Daten werden auf den verfügbaren Platz gekürzt. Natürlich können mit Protokollen, die Teilnachrichten unterstützen, das MSGPARTIAL-Flag verwendet werden, um Datenverlust zu verhindern. Brechen der Verbindung Sobald Sie mit einer Socket-Verbindung fertig sind, müssen Sie es schließen und alle mit diesem Socket-Handle verbundenen Ressourcen freigeben. Um die mit einem offenen Socket-Handle verbundenen Ressourcen tatsächlich freizugeben, verwenden Sie den Befehl closesocket (). Seien Sie sich jedoch bewusst, dass closesocket () kann einige negative Auswirkungen haben, je nachdem, wie es heißt, das kann zu Datenverlust führen. Aus diesem Grund sollte eine Verbindung mit der Funktion shutdown () vor einem Aufruf der Funktion closesocket () anmutig beendet werden. Diese beiden API-Funktionen werden als nächstes diskutiert. Shutdown () Um sicherzustellen, dass alle Daten, die eine Anwendung sendet, vom Peer empfangen wird, sollte eine gut geschriebene Anwendung dem Empfänger mitteilen, dass keine Daten mehr gesendet werden sollen. Ebenso sollte der Peer das gleiche tun. Dies wird als anmutiges Schließen bezeichnet und wird durch die Funktion shutdown () ausgeführt, die als: int shutdown (SOCKET s, int how) definiert ist. Wie Parameter SDRECEIVE, SDSEND oder SDBOTH sein kann. Für SDRECEIVE sind nachfolgende Aufrufe einer beliebigen Empfangsfunktion auf dem Socket nicht zulässig. Dies hat keine Auswirkung auf die unteren Protokollschichten. Und für TCP-Sockets, wenn Daten für den Empfang in die Warteschlange gestellt werden oder wenn Daten später ankommen, wird die Verbindung zurückgesetzt. Allerdings sind auf UDP-Sockets eingehende Daten immer noch akzeptiert und in der Warteschlange (weil shutdown () keine Bedeutung für verbindungslose Protokolle hat). Für SDSEND sind nachfolgende Aufrufe zu einer Sendefunktion nicht zulässig. Bei TCP-Sockeln bewirkt dies, dass ein FIN-Paket generiert wird, nachdem alle Daten gesendet und vom Empfänger quittiert wurden. Schließlich deaktiviert SDBOTH beide Sende und empfängt. Beachten Sie, dass nicht alle verbindungsorientierten Protokolle eine anmutige Schließung unterstützen, was die Shutdown () API ausführt. Für diese Protokolle (wie zB ATM) muss nur closesocket () aufgerufen werden, um die Sitzung zu beenden. Eine Fahne, die beschreibt, welche Arten von Operationen in der folgenden Tabelle zusammengefasst sind. Mögliche Werte für dieses Flag werden in der Headsdatei Winsock2.h aufgelistet. Sobald die Funktion shutdown () aufgerufen wird, um Sende, Empfang oder beide zu deaktivieren, gibt es keine Methode, um Sende oder Empfang für die vorhandene Socket-Verbindung wieder zu aktivieren. Eine Anwendung sollte sich nicht darauf verlassen, dass sie eine Steckdose wiederverwenden kann, nachdem sie heruntergefahren wurde. Insbesondere ist ein Windows Sockets-Provider nicht erforderlich, um die Verwendung von connect () auf einem Socket zu unterstützen, der heruntergefahren wurde. Wenn eine Anwendung eine Steckdose wiederverwenden möchte, sollte die Funktion DisconnectEx () mit dem Parameter dwFlags auf TFREUSESOCKET aufgerufen werden, um eine Verbindung auf einem Sockel zu schließen und den zu verwendenden Socket-Handle vorzubereiten. Wenn die DisconnectEx () - Anforderung abgeschlossen ist, kann der Socket-Handle an die Funktion AcceptEx () oder ConnectEx () übergeben werden. Wenn eine Anwendung einen Socket wiederverwenden möchte, können die Funktionen TransmitFile () oder TransmitPackets () mit dem Parameter dwFlags mit TFDISCONNECT und TFREUSESOCKET aufgerufen werden, um die Verbindung zu trennen, nachdem alle Daten für die Übertragung in die Warteschlange gestellt wurden und den zu verwendenden Socket-Handle vorbereitet. Wenn die TransmitFile () - Anforderung abgeschlossen ist, kann der Socket-Handle an den zuvor verwendeten Verbindungsaufruf übergeben werden, z. B. AcceptEx () oder ConnectEx (). When the TransmitPackets() function completes, the socket handle can be passed to the AcceptEx() function. Take note that the socket level disconnect is subject to the behavior of the underlying transport. For example, a TCP socket may be subject to the TCP TIMEWAIT state, causing the DisconnectEx(), TransmitFile(), or TransmitPackets() call to be delayed. closesocket() The closesocket() function closes a socket and is defined as: int closesocket (SOCKET s) If no error occurs, closesocket() returns zero. Otherwise, a value of SOCKETERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError(). The socket is marked as nonblocking, but the lonoff member of the linger structure is set to non-zero and the llinger member of the linger structure is set to a nonzero timeout value. Calling closesocket() releases the socket descriptor and any further calls using the socket fail with WSAENOTSOCK. If there are no other references to this socket, all resources associated with the descriptor are released. This includes discarding any queued data. Pending synchronous calls issued by any thread in this process are canceled without posting any notification messages. Pending overlapped operations are also canceled. Any event, completion routine, or completion port that is associated with the overlapped operation is performed but will fail with the error WSAOPERATIONABORTED. In addition, one other factor influences the behavior of closesocket(): whether the socket option SOLINGER has been set. An application should always have a matching call to closesocket() for each successful call to socket to return any socket resources to the system. TCP ReceiverServer With select() Example 1. While in the Visual C IDE, click File menu gt Project sub menu to create a new project. 2. Select Win32 for the Project types: and Win32 Console Application for the Templates. Put the project and solution name. Adjust the project location if needed and click OK. 3. Click Next for the Win32 Application Wizard Overview page. We will remove all the unnecessary project items. 4. In the Application page, select Empty project for the Additional options. Leave others as given and click Finish. 5. Next, we need to add new source file. Click Project menu gt Add New Item sub menu or select the project folder in the Solution Explorer gt Select Add menu gt Select New Item sub menu. 6. Select C File (.cpp) for the Templates. Put the source file name and click Add. Although the extension is. cpp, Visual C IDE will recognize that the source code used is C based on the Compile as C Code (TC) option which will be set in the project property page later. 7. Now, add the source code as given below. A sample of the select() return value int recvTimeOutTCP(SOCKET socket, long sec, long usec)

Comments

Popular posts from this blog

Is Binary Options Trading Halal Chinese

No Stop Hedged Grid Forex Handelssystem

Life Of A Forex Trader