27. januar 2003 - 17:09Der er
20 kommentarer og 1 løsning
SocketChannels
Hey.
Jeg forsøger at ombygge et eksempel fra www.javaworld.com (http://www.javaworld.com/javaworld/jw-09-2001/jw-0907-merlin.html), en webserver der anvender de nye java.nio pakker, fra webserver (altså stateless connections) til en server, hvor SocketChannelsne bliver holdt åbent, indtil aktivt lukket af enten server eller klient.
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
Arne_v, det håbede jeg også, men det er tilsyneladende ikke tilfældet.
Hvis jeg, med ovenstående kode, tilslutter en klient, og skriver "ABC123" og trykker ENTER, skriver Serveren, som det måtte forventes: Received: ABC123
Man måtte nu gå ud fra, at ReadBuffer igen var tomt (på den ene eller anden måde), men skriver jeg igen "DEF456", Skriver serveren: Received: ABC123 DEF456
Dette fortsætter så, skriver man DØ NU!, kommer teksten:
Det var sært, hele teksten kom ikke med?!... Sært, se bort fra ovenstående kommentar, og regn med denne i stedet for: ------- Arne_v, det håbede jeg også, men det er tilsyneladende ikke tilfældet.
Hvis jeg, med ovenstående kode, tilslutter en klient, og skriver "ABC123" og trykker ENTER, skriver Serveren, som det måtte forventes: Received: ABC123
Man måtte nu gå ud fra, at ReadBuffer igen var tomt (på den ene eller anden måde), men skriver jeg igen "DEF456", Skriver serveren: Received: ABC123 DEF456
Dette fortsætter så, skriver man DØ NU!, kommer teksten: Received: ABC123 DEF456 DØ NU!
Det bekymre mig bare, at den tidligere data bliver hængende i systemet. Det er ikke sjovt hvis den bibeholder alt data fra alle måske 3000 (hypotese) connections i RAMene?
Og hvis du laver en: key.attach(null); på et passende sted i koden (=når du er færdig med en request og er klar til næste), så skulle du starte forfra !
Det viste sig ikke helt at være det der var løsningen (dog tæt på): protected void parseRequest(SelectionKey key) throws Exception { SocketChannel incomingChannel = (SocketChannel) key.channel(); Socket incomingSocket = incomingChannel.socket();
try { int bytesRead = incomingChannel.read(readBuffer); readBuffer.flip(); String result = asciiDecoder.decode(readBuffer).toString(); readBuffer.clear();
Tilsyneladende (det skal jeg vidst lige undersøge!), er attechmentet et StringBuffer (eller noget der er kombatibelt med det?).
Dette attachment bliver ved med at være der, i hele SocketChannelens registration. Så den skal nulstilles når man er færdig med den.
Det virker logisk nok.
Iøvrigt ser nio pakkerne ud til på en meget fin måde, at tackle problemet med, at det ikke umiddelbart er til at vide, om en klient har lukket forbindelsen.
Et andet spørgsmål (det er længe siden jeg har haft fat i de basale ting i Java)... Abstract class. De kan kun extendes, og sker dette, skal den nedarvende klasse implementere alle metoder i den abstrakte klasse?
SocketChannel klassen er nemlig abstrakt (den bliver oprettet af en factory klasse - hedder det vidst?), ved navn ServerSocketChannel.
Jeg vil nemlig godt holde tjek på mine klienters data (et bruger Id), ved at lave en klasse (ClientChannel extends SocketChannel), men dette går jo ikke?, da jeg tilsyneladende ikke må nedarbejde, uden at overskrive ALLE metoder?
Okey... Men SocketChannel extender selv en AbstractClass: AbstractSelectableChannel ?
Løsningen er altså, lave public class ClientChannel extends AbstractSelectableChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel
Og lade ALLE metodekald, gennemtvunget abstrakt klasse og interfaces, gå direkte til en SocketChannel?
Jeg tror desværre livet er pain in the ass denne gang.
Ideen med NIO pakkerne, er at en SocketChannel har en Selector registretet. Denne selector kan kun registere ting, der er "SelectableChannels", altså er af typen AbstractSelectableChannel.
Selectorens opgave, er at lytte (så vidt jeg kan forstå) efter I/O Events (i dette tilfælde, om der er modtaget noget data).
Alt sammen er nonblocking, så man kan spare mange Threads i store applikationer.
Ja, jeg nærlæste det lidt - det objekt der er som attatchment, er noget man bestemmer når man registere SocketChannelen til dens Selector - jeg har lavet en ClientConnection, som kan håndtere de sager - det giver en meget mere stilfuld struktur i programmet, end man kunne opnå ved det gamle socketsystem.
Desværre kan én selector dog kun have 63 channels registeret :/... Så jeg har måtte lave en "ReadSelectorPool", som kan håndtere en masse af dem.
Men det virker perfekt anyway. 63 klienter / tråd er ok.
Tak for hjælpen - jeg vil godt give dig point, hvis du vil ha' dem - bare send et svar :)
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.