Avatar billede philox Nybegynder
31. marts 2003 - 00:12 Der er 36 kommentarer og
1 løsning

Socket og getInputStream()-problemer

Hej,
Jeg har en server, der opretter en "service-thread" for hver client der connecter.

Denne service-thread kan fint få gang i
getInputStream() og getOutputStream().
Problemet er klienten, den kan godt få fat i getOutputStream() og denne stream "virker". Men jeg kan ikke fået lavet en ObjectInputStream i klienten. Ethvert forsøg på at oprette en sådan stream resulterer vist i, at owner-threaded bliver 'blocked' (Klienten kører dog som egen thread)

Jeg kan godt få en BufferedReader til at virke, men kun hvis jeg bruge 'Stream'.ready() (Det virker meget underligt, at .ready() skulle gøre underværker)

Det følgende er ikke komplet java-kode, men nærmere skitser:

//Service klassen
class ClientService implements Runnable
{
...
private ObjectInputStream input = null;
private ObjectOutputStream output = null;
ClientService(Socket socket)
{
  ...
  input = new ObjectInputStream(
                      socket.getInputStream());
  output = new ObjectInputStream(
                socket.getOutputStream(),true);
  ...
}

public void run()
{
  //Skriver og læser snedige ting fra
  //streams'ne
}

//Klient klassen
class client
{
  private Socket client = null;
  private ObjectOutputStream output = null;
  private ObjectInputStream input = null;
  ...
  client()
  {
  ...
  client = new Socket("127.0.0.1", 3017);
  output = new ObjectOutputStream(
                    client.getOutputStream());
  //Oprettelsen af ObjectInputStream 'blocker'
  //den udførende tråd.
  //FEJL HER?
  input = new ObjectInputStream(
                      client.getInputStream());
  }
}
Avatar billede arne_v Ekspert
31. marts 2003 - 07:33 #1
Jeg har set lignende konstruktioner virke, så det er ikke principielt
umuligt.

Men du må have lavet en tyrk-fejl i:

ClientService(Socket socket)
{
  ...
  input = new ObjectInputStream(
                      socket.getInputStream());
  output = new ObjectInputStream(
                socket.getOutputStream(),true);
  ...
}
Avatar billede philox Nybegynder
31. marts 2003 - 11:57 #2
Jeg begik åbenbart en java-no-no.
Det var rækkefølgen af getStreams, der var afgørende.
Da jeg brugte:
Server:
  getInputStream();
  getOutputStream();

Client:
  getInputStream();
  getOutputStream();

hang de, alle andre kombinationer virker.
Avatar billede philox Nybegynder
31. marts 2003 - 14:15 #3
output = new ObjectInputStream(
                socket.getOutputStream(),true);
men ja, det var en copy-paste fejl der slap forbi i mit indlæg her :-)
Avatar billede philox Nybegynder
31. marts 2003 - 15:55 #4
Det lader til, at den ikke kan li' at jeg har 2 threads (client og server) der begge skriver/læser til deres respektive streams.
Er løsningen på problemet at lave et ekstra socket? (Det virker bestemt ikke optimalt)
Avatar billede arne_v Ekspert
31. marts 2003 - 15:59 #5
Det kan jeg svare på !

Hvis du bruger Sockets og Object*Stream i en multithreaded
applikation skal du selv synkronisere adgangen ellers kan det
gå meget galt.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:01 #6
Lav f.eks. en:

public static final X x = new X();

og brug:

synchronized(x) {
    ...
}

synchronized(Klasse.x) {
    ...
}

og put alle read & write indeni.
Avatar billede philox Nybegynder
31. marts 2003 - 16:10 #7
Jeg prøver det straks :-)
Avatar billede philox Nybegynder
31. marts 2003 - 16:17 #8
Selve klienten er består kun af en enkelt thread, så her behøves synkronisering ikke.

Hvilke threads er det, der kan "forstyrre" hinanden? Hver enkelt thread har jo sit egen socket.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:22 #9
Det kan gå galt hvis der er to tråde der accesser det samme objekt.

write+write og read+read ved jeg kan give problemer (bitter erfaring !)

Jeg formoder at read+write også kan gøre det.
Avatar billede philox Nybegynder
31. marts 2003 - 16:25 #10
//Et eksempel på en client

import java.net.*;
import java.io.*;
import java.util.*;

class TestClient implements Runnable
{
    Socket socket = null;
    ObjectInputStream input = null;
    ObjectOutputStream output = null;

    List phil = null;


    TestClient()
    {
      try
      {
            socket = new Socket("127.0.0.1", 700);
        output = new ObjectOutputStream(
                                          socket.getOutputStream());
        input = new ObjectInputStream(socket.getInputStream());
        Thread thread = new Thread(this);
        thread.start();
    }
    catch (Exception e)
    { }
    }

    public void run()
    {
      while(true)
      {
        try
        {
          phil = (LinkedList) input.readObject();
          for (int i = 0; i < phil.size(); i++)
          {
        System.out.println("ClientInt: " + phil.get(i));
        int temp = ((Integer) phil.get(i)).intValue();
        phil.set(i, new Integer(temp + 1));
              }
              output.writeObject(phil);
      }
      catch(Exception e)
      {
        System.err.println(e);
          }
    }
      }

      public static void main(String args[])
      {   
    new TestClient();
      }
}
Avatar billede philox Nybegynder
31. marts 2003 - 16:27 #11
Er det fordi "java" selv opretter tråde til håndtering af de forskellige streams? Det kunne forklare den "alternative" opførsel.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:30 #12
Instantierer du mere end et objekt af typen TestClient ?
Avatar billede philox Nybegynder
31. marts 2003 - 16:31 #13
Nej, og planen er at TestClienten startes på andre maskiner.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:31 #14
Nej. Java bør ikke oprette "behind-the-scene" threads.

Hvordan ser trådene ud på server siden ?
Avatar billede philox Nybegynder
31. marts 2003 - 16:33 #15
En server-thread (den med ServerSocket.accept() )
En serverService-thread, den der får overført det socket .accept() producerer.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:34 #16
Alt lyder OK.

Har du mulighed for at prøve at køre client i en anden JVM.

Jeg spekulerer lidt på om JVM'en laver kage i den fordi både
sender og receiver er i samme JVM.
Avatar billede philox Nybegynder
31. marts 2003 - 16:36 #17
Ja, men problemet er der vist stadig (jeg har nemlig selv mistænkt det samme, så jeg har nu build 1.4.1_02-b06)
Avatar billede philox Nybegynder
31. marts 2003 - 16:37 #18
Kan det være noget med at bl.a. readObject blocker hele tråden, hvis der ikke er noget at "læse" fra streamen?
Jeg mistænker det stærkt, men ethvert kald af 'stream'.available() returnerer 0, så jeg kan ikke se om der er data på den måde.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:40 #19
Med anden JVM mente jeg i.s.f. en tråd i samme JVM som server at
have client som en standalone app i sin egen JVM.

Du har også forsøgt med forskellige JVM's ?

[der har været en del spørgsmål de sidste dage med 1.4.1_02 problemer]
Avatar billede philox Nybegynder
31. marts 2003 - 16:42 #20
Maskine 1: Starter serveren.
Maskine 2: Starter clienten (kan dog ikke huske JRE-versionen her)
Avatar billede arne_v Ekspert
31. marts 2003 - 16:43 #21
readObject blocker !
Avatar billede philox Nybegynder
31. marts 2003 - 16:44 #22
Jeg har også prøvet at køre begge lokalt men med hvert sit "consol"-window. I texpad bruger jeg run på hver java-fil, hvilket resulter i 2 JVM'er ik'?
Avatar billede arne_v Ekspert
31. marts 2003 - 16:45 #23
available() skal ikke returnere 0, hvis der er noget ifølge Java API Doc.
Avatar billede philox Nybegynder
31. marts 2003 - 16:45 #24
"readObject blocker!"
Men jeg kan ikke lure hvordan, jeg ser om streamen er "klar", og så betyder rækkefølgen af write/reads lige pludselig rigtig meget!
Avatar billede philox Nybegynder
31. marts 2003 - 16:48 #25
Det tyder på noget deadlock-snask :-(
Avatar billede arne_v Ekspert
31. marts 2003 - 16:48 #26
Jo 2 console-vinduer og 2 java-kommandoer => 2 JVM'er.
Avatar billede arne_v Ekspert
31. marts 2003 - 16:51 #27
Standard design er normalt:

A)  uafhænig traffik client <-> server

    2 sockets - 1 for read + 1 for write
    2 threads

B)  request-response protokol

    1 socket
    1 thread
Avatar billede arne_v Ekspert
31. marts 2003 - 16:52 #28
I tilfælde B skal client så lave write+read mens server skal lave
read+write.

I tilfælde B kan read & write komme i vilkårlig række-følge men med
2 sockets og 2 threads virker det også.
Avatar billede philox Nybegynder
31. marts 2003 - 16:52 #29
Det er model-A, jeg sigter efter.
Så plan "snedig" er, at give serverServicen OG klienten hver 2 threads og 2 sockets?
Avatar billede philox Nybegynder
31. marts 2003 - 16:54 #30
Min client sender hele tiden sin "position" og serveren sender hele tiden alles "position", de svarer ikke på hinandens beskeder (som det er nu)
Avatar billede arne_v Ekspert
31. marts 2003 - 17:00 #31
"position" - det lyder som et multi-player spil.

Jeg tænker straks i baner a la:

hver client har 2 sockets til server, en client->server og en server->client

client har en GUI

keyboard/mouse events trigger writes til client->server socket

der er en baggrunds thread som læser fra server->client socket
og opdaterer GUI

server lytter på port

når der connectes til server laves 1 tråd som læser fra client->server
socket og opdaterer globale billede

server har også en separat tråd som sender opdateringer af det
globale billede ud på server->client socket
Avatar billede arne_v Ekspert
31. marts 2003 - 17:01 #32
Det kan også laves på andre måder.

Men ovenstående var mit bedste 60 sekunders design.
Avatar billede philox Nybegynder
31. marts 2003 - 17:03 #33
Præcis min ide :-) (og spil-delen var god nok)
Tror jeg lod mig forblænde af muligheden for en slags "full-duplex" på et socket.
Avatar billede swaq Nybegynder
31. marts 2003 - 19:06 #34
Hej Philox, jeg sagde jo at arne_v var et omvandrerne opslagsværk :-)

God ressource at kunne bruge af!
Avatar billede arne_v Ekspert
31. marts 2003 - 19:11 #35
I kender hinanden ?
Avatar billede swaq Nybegynder
31. marts 2003 - 21:34 #36
Jep!, Philox havde et problem alá det du hjalp mig med, så jeg anbefalede eksperten.dk/arne_v :-)

Håber det er ok...
Avatar billede philox Nybegynder
31. marts 2003 - 22:29 #37
:-)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester