SocketanslutningarFlash Player 9 och senare, Adobe AIR 1.0 och senare En socket är en typ av nätverksanslutning som upprättas mellan två datorprocesser. Vanligtvis körs processerna på två olika datorer anslutna till samma IP-nätverk. Men de anslutna processerna kan köras på samma dator med IP-adressen för den lokala värden. Adobe Flash Player stöder TCP-socketanslutningar på klientsidan. Ett Flash Player-program kan ansluta till en annan process genom att fungera som socketserver, men kan inte godkänna en inkommande anslutningsbegäran från andra processer. Ett Flash Player-program kan med andra ord ansluta till en TCP-server, men kan inte fungera som en. Flash Player API:et innehåller också klassen XMLSocket. Klassen XMLSocket använder ett protokoll specifikt för Flash Player som gör det möjligt att utbyta XML-meddelanden med en server som stöder det protokollet. Klassen XMLSocket introducerades i ActionScript 1 och stöds fortfarande för att ge bakåtkompatibilitet. Generellt sett bör Socket-klassen användas för nya program, såvida du inte ansluter till en server som skapats specifikt för att kommunicera med Flash XMLSockets. Adobe AIR innehåller flera klasser för socketbaserad nätverksprogrammering. AIR-program kan fungera som TCP-socketservrar med klassen ServerSocket och kan ansluta till socketservrar som kräver SSL- eller TLS-säkerhet med klassen SecureSocket. AIR-program kan också skicka och ta emot UDP-meddelanden (Universal Datagram Protocol) med klassen DatagramSocket. TCP-socketarTransmission Control Protocol (TCP) är ett sätt att utbyta meddelanden över en beständig nätverksanslutning. TCP garanterar att skickade meddelanden kommer fram i rätt ordning (bortsett från vid stora nätverksproblem). TCP-anslutningar kräver en "klient" och en "server". Flash Player kan skapa klientsocketar. Adobe AIR kan dessutom skapa serversocketar. Följande ActionScript-API:er tillhandahåller TCP-anslutningar:
Binära klientsocketarEn binär socketanslutning liknar en XML-socket förutom att klienten och servern inte är begränsade till att utbyta XML-meddelanden. Anslutningen kan i stället överföra data som binär information. Det gör att du kan ansluta till ett brett utbud av tjänster, däribland e-postservrar (POP3, SMTP och IMAP) och nyhetsservrar (NNTP). Socket, klassMed klassen Socket kan du skapa socketanslutningar och läsa och skriva binära rådata. Klassen Socket är användbar när du arbetar med servrar som har binära protokoll. Genom att använda binära socketanslutningar kan du skriva kod som möjliggör interaktion med flera olika Internet-protokoll, till exempel POP3, SMTP, IMAP och NNTP. Detta innebär i sin tur att dina program kan anslutas till e-post- och nyhetsservrar. Flash Player kan samverka med en server genom att använda den serverns binära protokoll direkt. Vissa servrar använder bigendian-byteordningen, medan andra använder littleendian-byteordningen. De flesta servrar på Internet använder bigendian-byteordningen eftersom ”nätverksbyteordningen” är bigendian. Littleendian-byteordningen är populär eftersom den används av Intel® x86-arkitekturen. Du bör använda den endian-byteordning som matchar byteordningen för den server som sänder eller tar emot data. Alla åtgärder som utförs av IDataInput- och IDataOutput-gränssnitten, och klasserna som implementerar de gränssnitten (ByteArray, Socket och URLStream), är som standard kodade i formatet bigendian, d.v.s. med den viktigaste byten först. Denna standardbyteordning har valts för att matcha Java och den officiella nätverksbyteordningen. Om du vill ändra byteordningen som används till bigendian eller littleendian kan du ställa in egenskapen endian på Endian.BIG_ENDIAN eller Endian.LITTLE_ENDIAN. Klassen Socket ärver alla de metoder som definieras av gränssnitten IDataInput och IDataOutput (finns i paketet flash.utils). De här metoderna måste användas för att skriva till och läsa från socketen. Mer information finns i: Säkra klientsocketar (AIR)Du kan använda klassen SecureSocket om du vill ansluta till socketservrar som använder Secure Sockets Layer version 4 (SSLv4) eller Transport Layer Security version 1 (TLSv1). Det finns tre fördelar med en säker socket: serverautentisering, dataintegritet och meddelandesekretess. Körningen autentiserar en server med hjälp av servercertifikatet och förhållandet till rotcertifikaten eller de mellanliggande certifikaten från certifikatutfärdare i användarens förtroendearkiv. Körningstiden beror på de krypteringsalgoritmer som används av SSL- och TSL-protokollimplementeringar för att tillhandahålla dataintegritet och meddelandesekretess. När du ansluter till en server med objektet SecureSocket valideras servercertifikatet av körtiden med hjälp av certifikatets förtroendearkiv. I Windows och Mac tillhandahålls förtroendearkivet av operativsystemet. I Linux tillhandahålls ett eget förtroendearkiv av körningen. Om inte servercertifikatet är giltigt eller betrott skickas en ioError-händelse av körningstiden. Du kan kontrollera egenskapen serverCertificateStatus för objektet SecureSocket för att fastställa varför valideringen misslyckades. Det tillhandahålls ingen åtgärd för att kommunicera med en server som inte har något giltigt och betrott certifikat. Klassen CertificateStatus definierar strängkonstanter som representerar de möjliga valideringsresultaten:
För kommunikation med ett SecureSocket-objekt krävs en server som använder ett säkert protokoll och har ett giltigt, betrott certifikat. För övrigt är det samma sak att använda ett SecureSocket-objekt som att använda ett Socket-objekt. Det finns inte stöd för SecureSocket-objektet på alla plattformar. Använd egenskapen isSupported i klassen SecureSocket för att testa om det finns stöd i körtiden för att använda SecureSocket-objektet på den aktuella klientdatorn. Mer information finns i: Exempel på TCP-socket: skapa en Telnet-klientTelnet-exemplet visar tekniker som kan användas för att ansluta till en fjärrserver och överföra data med hjälp av klassen Socket. Exemplet demonstrerar följande tekniker:
Programfilerna för det här exemplet finns på www.adobe.com/go/learn_programmingAS3samples_flash_se. Telnet-programfilerna finns i mappen Samples/Telnet. Programmet består av följande filer:
Översikt över Telnet-socketprogrammetHuvudfilen TelnetSocket.mxml ansvarar för att skapa användargränssnittet (UI) för hela programmet. Utöver användargränssnittet definierar den här filen även två metoder, login() och sendCommand(), för att ansluta användaren till den angivna servern. Följande kod anger ActionScript i huvudprogramfilen: import com.example.programmingas3.socket.Telnet; private var telnetClient:Telnet; private function connect():void { telnetClient = new Telnet(serverName.text, int(portNumber.text), output); console.title = "Connecting to " + serverName.text + ":" + portNumber.text; console.enabled = true; } private function sendCommand():void { var ba:ByteArray = new ByteArray(); ba.writeMultiByte(command.text + "\n", "UTF-8"); telnetClient.writeBytesToSocket(ba); command.text = ""; } Den första raden kod importerar klassen Telnet från det anpassade paketet com.example.programmingas.socket. Den andra raden kod deklarerar en instans av klassen Telnet, telnetClient, som kommer att initieras senare av metoden connect(). Sedan deklareras metoden connect() och initierar den tidigare deklarerade telnetClient-variabeln. Den här metoden skickar det av användaren angivna Telnet-servernamnet, Telnet-serverporten och en referens till en TextArea-komponent i visningslistan, som används för att visa textsvaren från socketservern. De sista två raderna för metoden connect() ställer in egenskapen title för panelen och aktiverar Panel-komponenten, som gör att användaren kan skicka data till fjärrservern. Den sista metoden i huvudprogramfilen, sendCommand(), används för att skicka användarens kommandon till fjärrservern som ett ByteArray-objekt. Översikt över klassen TelnetKlassen Telnet ansvarar för att ansluta till Telnet-fjärrservern och för att skicka/ta emot data. Klassen Telnet deklarerar följande privata variabler: private var serverURL:String; private var portNumber:int; private var socket:Socket; private var ta:TextArea; private var state:int = 0; Den första variabeln, serverURL, innehåller den av användaren angivna serveradressen som anslutningen berör. Den andra variabeln, portNumber, är portnumret som Telnet-servern för närvarande körs på. Standardinställningen innebär att Telnet-tjänsten körs på port 23. Den tredje variabeln, socket, är en Socket-instans som kommer att försöka att ansluta till servern som har definierats av variablerna serverURL och portNumber. Den fjärde variabeln, ta, är en referens till en TextArea-komponentinstans på scenen. Den här komponenten används för att visa svar från Telnet-fjärrservern och eventuella felmeddelanden. Den sista variabeln, state, är ett numeriskt värde som används för att avgöra vilka alternativ din Telnet-klient stöder. Som du redan har sett anropas klassen Telnets konstruktorfunktion av metoden connect() i huvudprogramfilen. Telnet-konstruktorn har tre parametrar: server, port och output. Parametrarna server och port anger servernamnet och portnumret där Telnet-servern körs. Den sista parametern, output, är en referens till en TextArea-komponentinstans på scenen där serverutdata kommer att visas för användarna. public function Telnet(server:String, port:int, output:TextArea) { serverURL = server; portNumber = port; ta = output; socket = new Socket(); socket.addEventListener(Event.CONNECT, connectHandler); socket.addEventListener(Event.CLOSE, closeHandler); socket.addEventListener(ErrorEvent.ERROR, errorHandler); socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); socket.addEventListener(ProgressEvent.SOCKET_DATA, dataHandler); Security.loadPolicyFile("http://" + serverURL + "/crossdomain.xml"); try { msg("Trying to connect to " + serverURL + ":" + portNumber + "\n"); socket.connect(serverURL, portNumber); } catch (error:Error) { msg(error.message + "\n"); socket.close(); } } Skriva data till en socketOm du vill skriva data till en socketanslutning anropar du någon av skrivmetoderna i klassen Socket. De här skrivmetoderna omfattar writeBoolean(), writeByte(), writeBytes()och writeDouble() med flera. Sedan tömmer du dina data i utdatabufferten med hjälp av metoden flush(). På Telnet-servern skrivs data till socketanslutningen med hjälp av metoden writeBytes(), som tar bytearrayen som parameter och skickar den till utdatabufferten. Koden för metoden writeBytesToSocket() är följande: public function writeBytesToSocket(ba:ByteArray):void { socket.writeBytes(ba); socket.flush(); } Den här metoden anropas av metoden sendCommand() i huvudprogramfilen. Visa meddelanden från socketservernVarje gång ett meddelande tas emot från socketservern, eller när en händelse inträffar, anropas den anpassade metoden msg(). Den här metoden bifogar en sträng till TextArea på scenen och anropar en anpassad setScroll()-metod, vilket gör att TextArea-komponenten rullar så att den hamnar allra längst ned. Koden för metoden msg() är följande: private function msg(value:String):void { ta.text += value; setScroll(); } Om du inte rullade innehållet i TextArea-komponenten automatiskt måste användarna dra rullningslisterna i textområdet manuellt för att se det senaste svaret från servern. Rulla en TextArea-komponentMetoden setScroll() innehåller en enda ActionScript-rad som rullar TextArea-komponentens innehåll lodrätt så att användaren kan se den sista raden med returnerad text. Följande utdrag visar metoden setScroll(): public function setScroll():void { ta.verticalScrollPosition = ta.maxVerticalScrollPosition; } Den här metoden ställer in egenskapen verticalScrollPosition, som är radnumret för den översta raden med tecken som visas, och ställer in värdet för egenskapen maxVerticalScrollPosition. XML-socketarMed en XML-socket kan du skapa en anslutning till en fjärrserver som förblir öppen tills den uttryckligen stängs. Du kan utbyta strängdata, till exempel XML, mellan servern och klienten. En annan fördel med att använda en XML-socketserver är att klienten inte uttryckligen behöver begära data. Servern kan skicka data utan att vänta på en begäran och skicka data till alla anslutna klienter. För Flash Player och Adobe AIR-innehåll utanför programsandlådan kräver XML-socketanslutningar en socketprincipfil på målservern. Mer information finns i Webbplatsinställningar (principfiler) och Ansluta till socketar. Klassen XMLSocket kan inte gå igenom brandväggar automatiskt, eftersom XMLSocket i motsats till RTMP (Real-Time Messaging Protocol) saknar HTTP-tunnelkapacitet. Om du måste använda HTTP-tunnel bör du i stället använda Flash Remoting eller Flash Media Server (som har stöd för RTMP). Nedanstående begränsningar avser hur och var innehåll i Flash Player eller i ett AIR-program utanför programsäkerhetssandlådan kan ansluta till servern med hjälp av ett XMLSocket-objekt:
Obs! Det kan vara svårt att ställa in en server för att kommunicera med XMLSocket-objektet. Om programmet inte kräver realtidsinteraktivitet använder du klassen URLLoader i stället för XMLSocket.
Du kan använda metoderna XMLSocket.connect() och XMLSocket.send() för klassen XMLSocket för att överföra XML till och från en server via en socketanslutning. Med metoden XMLSocket.connect() upprättas en socketanslutning till en webbserverport. Med metoden XMLSocket.send() skickas ett XML-objekt till den server som har angetts i socketanslutningen. När du anropar metoden XMLSocket.connect() öppnar programmet en TCP/IP-anslutning till servern och anslutningen förblir öppen tills något av följande inträffar:
Ansluta till en server med klassen XMLSocketFör att kunna skapa en socketanslutning måste du skapa ett program på servern som väntar på en socketanslutningsbegäran och skickar ett svar till Flash Player eller AIR-programmet. Den här typen av program på servern kan skrivas i AIR eller i ett annat programmeringsspråk, till exempel Java, Python eller Perl. För att klassen XMLSocket ska kunna användas måste servern ha en daemon-process som förstår det enkla protokollet som klassen XMLSocket använder:
Skapa och ansluta till en Java XML-socketserverNedanstående kod visar en enkel XMLSocket-server skriven i Java som godtar inkommande anslutningar och visar de mottagna meddelandena i kommandotolksfönstret. En ny server skapas som standard på port 8080 på din lokala dator, men du kan ange ett annat portnummer när du startar servern från kommandoraden. Skapa ett nytt textdokument och lägg till följande kod: import java.io.*; import java.net.*; class SimpleServer { private static SimpleServer server; ServerSocket socket; Socket incoming; BufferedReader readerIn; PrintStream printOut; public static void main(String[] args) { int port = 8080; try { port = Integer.parseInt(args[0]); } catch (ArrayIndexOutOfBoundsException e) { // Catch exception and keep going. } server = new SimpleServer(port); } private SimpleServer(int port) { System.out.println(">> Starting SimpleServer"); try { socket = new ServerSocket(port); incoming = socket.accept(); readerIn = new BufferedReader(new InputStreamReader(incoming.getInputStream())); printOut = new PrintStream(incoming.getOutputStream()); printOut.println("Enter EXIT to exit.\r"); out("Enter EXIT to exit.\r"); boolean done = false; while (!done) { String str = readerIn.readLine(); if (str == null) { done = true; } else { out("Echo: " + str + "\r"); if(str.trim().equals("EXIT")) { done = true; } } incoming.close(); } } catch (Exception e) { System.out.println(e); } } private void out(String str) { printOut.println(str); System.out.println(str); } } Spara dokumentet på hårddisken som SimpleServer.java och kompilera det med hjälp av en Java-kompilator, vilket skapar en Java-klassfil med namnet SimpleServer.class. Du kan starta XMLSocket-servern genom att öppna en kommandotolk och skriva java SimpleServer. Filen SimpleServer.class kan finnas på valfri plats på din dator eller i nätverket. Den behöver inte placeras i rotkatalogen på webbservern. Om du inte kan starta servern för att filerna inte finns i Java-klassökvägen, kan du försöka att starta servern med java -classpath . SimpleServer. För att ansluta till XMLSocket från ditt program måste du skapa en ny instans av klassen XMLSocket och anropa metoden XMLSocket.connect() när du skickar ett värdnamn och portnummer enligt följande: var xmlsock:XMLSocket = new XMLSocket(); xmlsock.connect("127.0.0.1", 8080); Varje gång du tar emot data från servern skickas data-händelsen (flash.events.DataEvent.DATA). xmlsock.addEventListener(DataEvent.DATA, onData); private function onData(event:DataEvent):void { trace("[" + event.type + "] " + event.data); } Om du vill skicka data till XMLSocket-servern använder du metoden XMLSocket.send() och skickar ett XML-objekt eller -sträng. Flash Player konverterar den angivna parametern till ett String-objekt och skickar innehållet till XMLSocket-servern följt av en nollbyte (0). xmlsock.send(xmlFormattedData); Metoden XMLSocket.send() returnerar inte ett värde som anger om data kunde skickas. Om ett fel uppstår när data skickas returneras ett IOError-fel. Varje meddelande som du skickar till XML-socketservern måste sluta med ett radmatningstecken (\n). Mer information finns i XMLSocket. ServersocketarAnvänd klassen ServerSocket för att tillåta att andra processer ansluter till ditt program med hjälp av en TCP-socket (Transport Control Protocol). Anslutningsprocessen kan köras på den lokala datorn eller på någon annan dator som är ansluten till nätverket. När ett ServerSocket-objekt tar emot en anslutningsförfrågan skickas en connect-händelse. Objektet ServerSocketConnectEvent som skickas med händelsen innehåller ett Socket-objekt. Du kan använda det här socketobjektet för kommande kommunikation med andra processer. Så här lyssnar du efter inkommande socketanslutningar:
ServerSocket-objektet fortsätter att lyssna efter nya anslutningar tills du anropar metoden close(). Följande kodexempel illustrerar hur ett socketserverprogram skapas. Exemplet lyssnar efter inkommande anslutningar på port 8087. När en anslutning tas emot skickas ett meddelande (strängen "Connected.") av exemplet till klientens socket. Sedan skickas meddelanden som servern tagit emot tillbaka till klienten. package { import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.ServerSocketConnectEvent; import flash.net.ServerSocket; import flash.net.Socket; public class ServerSocketExample extends Sprite { private var serverSocket:ServerSocket; private var clientSockets:Array = new Array(); public function ServerSocketExample() { try { // Create the server socket serverSocket = new ServerSocket(); // Add the event listener serverSocket.addEventListener( Event.CONNECT, connectHandler ); serverSocket.addEventListener( Event.CLOSE, onClose ); // Bind to local port 8087 serverSocket.bind( 8087, "127.0.0.1" ); // Listen for connections serverSocket.listen(); trace( "Listening on " + serverSocket.localPort ); } catch(e:SecurityError) { trace(e); } } public function connectHandler(event:ServerSocketConnectEvent):void { //The socket is provided by the event object var socket:Socket = event.socket as Socket; clientSockets.push( socket ); socket.addEventListener( ProgressEvent.SOCKET_DATA, socketDataHandler); socket.addEventListener( Event.CLOSE, onClientClose ); socket.addEventListener( IOErrorEvent.IO_ERROR, onIOError ); //Send a connect message socket.writeUTFBytes("Connected."); socket.flush(); trace( "Sending connect message" ); } public function socketDataHandler(event:ProgressEvent):void { var socket:Socket = event.target as Socket //Read the message from the socket var message:String = socket.readUTFBytes( socket.bytesAvailable ); trace( "Received: " + message); // Echo the received message back to the sender message = "Echo -- " + message; socket.writeUTFBytes( message ); socket.flush(); trace( "Sending: " + message ); } private function onClientClose( event:Event ):void { trace( "Connection to client closed." ); //Should also remove from clientSockets array... } private function onIOError( errorEvent:IOErrorEvent ):void { trace( "IOError: " + errorEvent.text ); } private function onClose( event:Event ):void { trace( "Server socket closed by OS." ); } }} Mer information finns i: UDP-socketar (AIR)Universal Datagram Protocol (UDP) är ett sätt att utbyta meddelanden över en tillståndslös nätverksanslutning. Med UDP lämnas ingen garanti för att meddelanden levereras i ordning eller att de levereras över huvud taget. Med UDP brukar operativsystemets nätverkskod använda mindre tid för att konvertera, spåra och bekräfta meddelanden. Därför anländer UDP-meddelanden vanligtvis till målprogrammet med kortare fördröjning än vad TCP-meddelanden gör. UDP-socketkommunikation kan vara till hjälp när du måste skicka realtidsinformation, till exempel uppdaterade positioner i ett spel eller ljudpaket i ett ljudchattprogram. I sådana program accepteras en viss dataförlust och låg överföringsfördröjning är viktigare än garanterad leverans. För så gott som alla andra syften är TCP-socketar ett bättre val. AIR-programmet kan skicka och ta emot UDP-meddelanden med klasserna DatagramSocket och DatagramSocketDataEvent. Så här skickar du eller tar emot ett UDP-meddelande:
I följande kodexempel illustreras hur ett UDP-meddelande skickas och tas emot i ett program. I exemplet skickas ett enkelt meddelande som innehåller strängen "Hello." till måldatorn. Innehållet spåras också i samtliga mottagna meddelanden. package { import flash.display.Sprite; import flash.events.DatagramSocketDataEvent; import flash.events.Event; import flash.net.DatagramSocket; import flash.utils.ByteArray; public class DatagramSocketExample extends Sprite { private var datagramSocket:DatagramSocket; //The IP and port for this computer private var localIP:String = "192.168.0.1"; private var localPort:int = 55555; //The IP and port for the target computer private var targetIP:String = "192.168.0.2"; private var targetPort:int = 55555; public function DatagramSocketExample() { //Create the socket datagramSocket = new DatagramSocket(); datagramSocket.addEventListener( DatagramSocketDataEvent.DATA, dataReceived ); //Bind the socket to the local network interface and port datagramSocket.bind( localPort, localIP ); //Listen for incoming datagrams datagramSocket.receive(); //Create a message in a ByteArray var data:ByteArray = new ByteArray(); data.writeUTFBytes("Hello."); //Send the datagram message datagramSocket.send( data, 0, 0, targetIP, targetPort); } private function dataReceived( event:DatagramSocketDataEvent ):void { //Read the data from the datagram trace("Received from " + event.srcAddress + ":" + event.srcPort + "> " + event.data.readUTFBytes( event.data.bytesAvailable ) ); } }} Kom ihåg följande när du använder UDP-socketar:
Mer information finns i: IPv6-adresserFlash Player 9.0.115.0 och senare stöder IPv6 (Internet Protocol version 6). IPv6 är en version av Internetprotokollet med stöd för adresser med 128-bitar (en förbättring från den tidigare versionen IPv4 som har stöd för 32-bitar). Du kanske måste aktivera IPv6 i dina nätverksgränssnitt. Mer information finns i hjälpen för operativsystemet som dina data finns på. Om IPv6 stöds i operativsystemet kan du ange numeriska IPv6-adresser uttryckligen i URL:er inom hakparenteser ([]) på följande sätt: [2001:db8:ccc3:ffff:0:444d:555e:666f] Flash Player returnerar litterala IPv6-värden, enligt följande regler:
IPv6-värdena som Flash Player returnerar har följande undantag:
|
|