Gå til innhold

[Løst] Får ikke Socket Webtjener til å svare


Anbefalte innlegg

Hei!

Jeg trenger hjelp til siste deloppgave av en øving vi for tiden holder på med (sitter helt fast). Den går ut på å programmere en enkel webtjener ved hjelp av Socketprogrammering. Oppgaven lyder som følger:

 

Lag en enkel web-tjener basert på det du har lært så langt. For enkelhets skyld kan du lage en løsning som kun takler en klient.
Tjeneren skal når en nettleser kobler seg til returnere en velkomstmelding med formatteringen <H1>. Deretter skal det skrives ut headeren som nettleseren sender ved oppkobling (se under). Headeren vil bestå av flere linjer og disse skal skrives ut som en
punktliste (i HTML blir det altså <UL> <LI>).
Tips:
• Web-tjener lytter vanligvis på port 80 (på Linux må du da starte tjeneren som superbruker – da kun porter over 1024 er tilgengelig for vanlige brukere)
• Nettlesere sender en (HTTP-)header når de kobler seg opp til tjeneren (dette er gjennomgått i forbindelse med jsp-leksjonene – så det kan være greit å gjennoppfriske dette). Headeren avsluttes bestandig med en blank linje ( i java blir det noe slikt linje.equals(''''))
• Når man skal returnere innhold til nettleseren begynner også tjeneren alltid med en (HTTP-)header. Det du bør returnere til nettleser er altså noe slikt:
HTTP/1.0 200 OK
Content-Type: text/html
Her skal det være en tom-linje (skiller header fra kroppen)
<HTML><BODY>
<H1> Hilsen. Du har koblet deg opp til min enkle web-tjener </h1>
Header fra klient er:
<UL>
<LI> ...... </LI>
</UL>
</BODY></HTML>
• HUSK at web-tjeneren skal avslutte forbindelsen etter at informasjonen er sendt til nettleseren.
Bruk nettleser for å teste tjeneren din.

 

Problemet er at det i koden min ikke blir sendt noe data (i alle fall ikke som kommer frem på tjeneren (altså når man går inn på porten i nettleseren, localhost:1250 er siden tom, ingen kildekode)). Jeg fikk til det når jeg kun sendte testdata (uten html-kode), da hadde jeg riktignok println før jeg mottok data, har rekkefølge noe å si her? Fra klienten får man en GET-forespørsel, forventer den ETT svar? Altså at headeren med statuskode 200 osv samt nettsiden kommer i en println? Jeg tror ikke jeg er langt unna her, men er ikke helt sikker på hvordan man svarer på rett måte. Setter jeg opp port 80 får jeg feilmelding forresten, JavaVMBind og at den allerede er i bruk (noe som sikkert stemmer fint), jeg fikk inntrykk av at man skulle bruke den porten i øvingsteksten men siden jeg ikke fikk det til å fungere tok jeg 1250.

 

Her er koden jeg har så langt:

/*
 * WebTjener.java
 * Tjener som sender headerlinjer fra klient som liste tilbake.
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class WebTjener {

    public static void main(String [] args) throws IOException{
        final int PORTNR = 1250;

        ServerSocket tjener = new ServerSocket(PORTNR);
        System.out.println("Logg for tjenersiden. Nå venter vi...");
        Socket forbindelse = tjener.accept();  // venter inntil noen tar kontakt

    /* Åpner strømmer for kommunikasjon med klientprogrammet */
        InputStreamReader leseforbindelse
                = new InputStreamReader(forbindelse.getInputStream());
        BufferedReader leseren = new BufferedReader(leseforbindelse);
        PrintWriter skriveren = new PrintWriter(forbindelse.getOutputStream(), true);
        String tekst = "";

        String start = "<html><head><title>Velkommen</title></head><body><h1>Hilsen. Du har koblet deg opp til min enkle web-tjener</h1> Header fra klient er: <ul>";
        String slutt = "</ul></body></html>";

    /* Mottar data fra klienten */
        String enLinje = leseren.readLine();  // mottar en linje med tekst
        while (enLinje != null) {  // forbindelsen på klientsiden er lukket
            System.out.println("En klient skrev: " + enLinje);
            tekst += "<li>" + enLinje + "</li>";
            enLinje = leseren.readLine();
        }
        skriveren.println("HTTP/1.0 200 OK");
        skriveren.println("Content-Type: text/html");
        skriveren.println("");
        skriveren.println(start + tekst + slutt);

    /* Lukker forbindelsen */
        leseren.close();
        skriveren.close();
        forbindelse.close();
    }
}

På forhånd takk!

Lenke til kommentar
Videoannonse
Annonse

Jeg fikk høre at man skulle bruke \r\n for linjeskift i HTTP-headerlinjer samt at man ikke skulle bruke println, men print i stedet. Får det fortsatt ikke til men er muligens litt nærmere.

 

Dette er hva jeg har nå:

/*
 * WebTjener.java
 * Tjener som sender headerlinjer fra klient som liste tilbake.
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class WebTjener {

    public static void main(String [] args) throws IOException{
        final int portnr = 1250;

        ServerSocket tjener = new ServerSocket(portnr);
        System.out.println("Logg for tjenersiden. Nå venter vi...");
        Socket forbindelse = tjener.accept();  // venter inntil noen tar kontakt

        /* Åpner strømmer for kommunikasjon med klientprogrammet */
        InputStreamReader leseforbindelse
                = new InputStreamReader(forbindelse.getInputStream());
        BufferedReader leseren = new BufferedReader(leseforbindelse);
        PrintWriter skriveren = new PrintWriter(forbindelse.getOutputStream(), true);
        String tekst = "";

        String start = "<doctype !html><html><head><title>Velkommen</title></head><body><h1>Hilsen. Du har koblet deg opp til min enkle web-tjener</h1> Header fra klient er: <ul>";
        String slutt = "</ul></body></html>";

        /* Mottar data fra klienten */
        String enLinje = leseren.readLine();  // mottar en linje med tekst
        while (enLinje != null) {  // forbindelsen på klientsiden er lukket
            System.out.println("En klient skrev: " + enLinje);
            tekst += "<li>" + enLinje + "</li>";
            enLinje = leseren.readLine();
        }
        skriveren.print("HTTP/1.0 200 OK \r\n");
        skriveren.print("Content-Type: text/html; charset=UTF-8\r\n");
        skriveren.print(start + tekst + slutt);

        /* Lukker forbindelsen */
        leseren.close();
        skriveren.close();
        forbindelse.close();
    }
}
Lenke til kommentar

Du har glemt content-length: Som skal være med i headeren, for å si ifra om hvor stor bodyen er.

skriveren.print("HTTP/1.0 200 OK \r\n");
skriveren.print("Content-Type: text/html; charset=UTF-8\r\n");
skriveren.print("Content-Length: " + bodyLength + "\r\n");
skriveren.print("\r\n");
skriveren.print(start + tekst + slutt);
Endret av etse
  • Liker 1
Lenke til kommentar

 

Du har glemt content-length: Som skal være med i headeren, for å si ifra om hvor stor bodyen er.

skriveren.print("HTTP/1.0 200 OK \r\n");
skriveren.print("Content-Type: text/html; charset=UTF-8\r\n");
skriveren.print("Content-Length: " + bodyLength + "\r\n");
skriveren.print("\r\n");
skriveren.print(start + tekst + slutt);

 

Jeg får det enda ikke til, jeg får GET-forespørselen fra klienten når jeg kjører localhost:1250 i nettleseren, men siden bare laster helt til "Siden kan ikke vises" kommer, jeg får ikke noe svar fra tjener. Mulig jeg har misforstått bodyLength? Slik jeg har forstått det er det lengden som i antall tegn i body? Det er slik jeg gjorde det isåfall:

        int bodyLength = start.length() + tekst.length() + slutt.length();
        skriveren.print("HTTP/1.0 200 OK \r\n");
        skriveren.print("Content-Type: text/html; charset=utf-8\r\n");
        skriveren.print("Content-Length: " + bodyLength + "\r\n");
        skriveren.print("\r\n");
        skriveren.print(start + tekst + slutt);

Resten av koden er lik den i andre post. Her er svaret ifra nettleseren:

 

En klient skrev: GET / HTTP/1.1

En klient skrev: Host: localhost:1250

En klient skrev: User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0

En klient skrev: Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

En klient skrev: Accept-Language: no,nb-no;q=0.9,nb;q=0.8,no-no;q=0.6,nn-no;q=0.5,nn;q=0.4,en;q=0.3,en-us;q=0.1

En klient skrev: Accept-Encoding: gzip, deflate

En klient skrev: DNT: 1

En klient skrev: Connection: keep-alive

En klient skrev:

Endret av unbreakable163
Lenke til kommentar

Ja, du forstod hva jeg mente riktig der. Spørsmålet er da, sender serveren din i det heletatt noe som helst tilbake? Dette kan man lett teste ved å f.eks. bruke telnet å gjøre en manuell GET-request der.

 

Testet koden din, og problemet jeg fant var at programmet dit rett og slett aldri kommer ut av while-løkka - den oppdager rett og slett aldri slutten på headeren fra klienten. (den blanke linja). Forslag: Endre til "while (enLinje.equals("") != true) {", dette gjør at den vil lese helt til den får en blank linje - dette tolker den som "nå har jeg fått lest hele headeren fra klienten".

 

Du glemmer og å flushe streamen din, så man kan ikke garantere at ting blir sendt selv om ting hadde fungert fint. Så husk å legge til "skriveren.flush();" etter du har printet alt av data du ønsker å sende.

Endret av etse
  • Liker 1
Lenke til kommentar

Ja, du forstod hva jeg mente riktig der. Spørsmålet er da, sender serveren din i det heletatt noe som helst tilbake? Dette kan man lett teste ved å f.eks. bruke telnet å gjøre en manuell GET-request der.

 

Testet koden din, og her er problemer jeg fant var at programmet dit rett og slett aldri kommer ut av while-løkka - den oppdager rett og slett aldri slutten på headeren fra klienten. (den blanke linja)

 

Fikk koblet til med telnet, (altså cmd -> telnet localhost 1250). Fikk snakket med tjeneren, ikke at han sa stort:

 

 

Logg for tjenersiden. Nå venter vi...

En klient skrev: ssasd

En klient skrev: asd

En klient skrev: asd

Endret av unbreakable163
Lenke til kommentar

 

Ja, du forstod hva jeg mente riktig der. Spørsmålet er da, sender serveren din i det heletatt noe som helst tilbake? Dette kan man lett teste ved å f.eks. bruke telnet å gjøre en manuell GET-request der.

 

Testet koden din, og her er problemer jeg fant var at programmet dit rett og slett aldri kommer ut av while-løkka - den oppdager rett og slett aldri slutten på headeren fra klienten. (den blanke linja)

 

Fikk koblet til med telnet, (altså cmd -> telnet localhost 1250). Fikk snakket med tjeneren, ikke at han sa stort:

 

 

Logg for tjenersiden. Nå venter vi...

En klient skrev: ssasd

En klient skrev: asd

En klient skrev: asd

 

Husk at du skal avslutte header med en tom linje. Hadde du prøvd å sende tomme linjer ville du sett at den fortsatt bare stod i while-løkka uten å gå videre. Så anbefalingen er å prøve å sende en fullstendig gyldig header når man tester slike ting, og husk detaljer som en ekstra tom linje på slutten.

 

Tusen takk for hjelpen, det ordnet problemet. Det der hadde jeg aldri funnet ut av selv. Nå fungerer det utmerket.

 

Bra ting ordnet seg :)

  • Liker 1
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...