Toon posts:

[JAVA] server + multiple clients

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hoi,

Ik heb nu een simpele server... Zoiets als dit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public Console(int port) {

      try {
        ServerSocket server = new ServerSocket(port);
        Socket connection = null;
        while (true) {
            try {
              connection = server.accept();
              reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
              writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
            } catch (IOException e) {
            }
        } // end while
      } catch (IOException e) {
        System.out.println(e.getMessage());
      }
    }

Deze server draait op poort 6667 (willekeurig gekozen). Nu kan ik met de client connecten en alles gaat naar wens. Nu wil ik echter 2 keer tegelijk connecten op de server. Dit gaat mis. Het lijkt of er maar 1 client tegelijk aanwezig kan zijn. Is er iemand die weet hoe ik de server moet schrijven zodat meerdere clients tegelijk gebruik kunnen maken van de server (op dezelfde poort, serverside).

Bedankt!

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 27-08 13:53

chem

Reist de wereld rond

Op maandag 14 januari 2002 13:40 schreef razor_harm het volgende:
Deze server draait op poort 6667 (willekeurig gekozen)
kies dan een andere, 6667 is de standaard poort voor IRC :)

Klaar voor een nieuwe uitdaging.


Verwijderd

Topicstarter
Op maandag 14 januari 2002 13:53 schreef chem het volgende:

[..]

kies dan een andere, 6667 is de standaard poort voor IRC :)
Heel interessant, maar dat doet er verder helemaal niet toe...
Stel je anders voor dat poort 7271 gebruikt wordt ;)

  • wasigh
  • Registratie: Januari 2001
  • Niet online

wasigh

wasigh.blogspot.com

idd, maar 1 connectie tegelijkertijd, als je dat niet wil moet je de connectie regelen in een thread.

Verwijderd

Niet zo raar, je hebt toch maar 1 Socket die je voor elke connectie wilt gebruiken?

Oh en vergeet niet dat zodra je gaat luisten op je Socket (met wat voor reader dan ook) dat dat in een aparte thread moet zijn anders zal je code daar op hangen en kun je maar naar 1 client tegelijk luisteren.

Maak dus bijvoorbeeld op het moment van een incoming connection op je ServerSocket een instantie van een object dat Thread extend en een Socket in de constructor heeft.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Client extends Thread
{
   private Socket mySocket;
   private <een_of_andere_reader> myReader;
   private <een_of_andere_writer> myWriter;

   public Client(Socket aSocket)
   {
     mySocket = aSocket;
     // initieer je reader en writer
   }
 
   public void run()
   {
    // begin te luisteren op je reader
   }

   public void write(String s)
   {
    //schrijf naar je writer
   }
}

//en in je Console doe je 

while(true) { 
    new Client(server.accept()).start();
    // wil je de client gebruiken zet um dan even in een array ofzo, wel zo handig
}

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Dit is wel een geinig voorbeeldje... 't Is een HTTP servertje... Bron: Orreily's Java, Network Programming...

Let vooral op wat er gebeurt bij de accept() methode... Hier wordt het geredirect naar een of andere pool. Je kan natuurlijk net zo goed kiezen om een apart runnable object te maken wat de connectie voorsteld naar de client en deze na aanmaken op basis met onderandere de van accept() verkregen socket als input parameter voor de constructor.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import java.net.*;
import java.io.*;
import java.util.*;

public class JHTTP extends Thread {

  private File documentRootDirectory;
  private String indexFileName = "index.html";
  private ServerSocket server;
  private int numThreads = 50;
    
  public JHTTP(File documentRootDirectory, int port, 
   String indexFileName) throws IOException {
    
    if (!documentRootDirectory.isDirectory()) {
    throw new IOException(documentRootDirectory 
     + " does not exist as a directory"); 
    }
    this.documentRootDirectory = documentRootDirectory;
    this.indexFileName = indexFileName;
    this.server = new ServerSocket(port);
  }

  public JHTTP(File documentRootDirectory, int port) 
   throws IOException {
    this(documentRootDirectory, port, "index.html");
  }

  public JHTTP(File documentRootDirectory) throws IOException {
    this(documentRootDirectory, 80, "index.html");
  }

  public void run() {
  
    for (int i = 0; i < numThreads; i++) {
    Thread t = new Thread(
     new RequestProcessor(documentRootDirectory, indexFileName));
    t.start();   
    }
    System.out.println("Accepting connections on port " 
     + server.getLocalPort());
    System.out.println("Document Root: " + documentRootDirectory);
    while (true) {
    try {
      Socket request = server.accept();
      RequestProcessor.processRequest(request);
    }
    catch (IOException e) { 
    }   
    }
    
  }
  
  public static void main(String[] args) {

    // get the Document root
    File docroot;
    try {
    docroot = new File(args[0]);
    }
    catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Usage: java JHTTP docroot port indexfile");
    return;
    }
    
    // set the port to listen on
    int port;
    try {
    port = Integer.parseInt(args[1]);
    if (port < 0 || port > 65535) port = 80;
    }  
    catch (Exception e) {
    port = 80;
    }  
    
    try {       
    JHTTP webserver = new JHTTP(docroot, port);
    webserver.start();
    }
    catch (IOException e) {
    System.out.println("Server could not start because of an " 
     + e.getClass());
    System.out.println(e);
    }
  
  }

}


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import java.net.*;
import java.io.*;
import java.util.*;
    
public class RequestProcessor implements Runnable {
    
  private static List pool = new LinkedList();
  private File documentRootDirectory;
  private String indexFileName = "index.html";
  
  public RequestProcessor(File documentRootDirectory, 
   String indexFileName) {
      
    if (documentRootDirectory.isFile()) {
    throw new IllegalArgumentException(
     "documentRootDirectory must be a directory, not a file");   
    }
    this.documentRootDirectory = documentRootDirectory;
    try {
    this.documentRootDirectory 
     = documentRootDirectory.getCanonicalFile();
    }
    catch (IOException e) {
    }
    if (indexFileName != null) this.indexFileName = indexFileName;
  }
  
  public static void processRequest(Socket request) {
    
    synchronized (pool) {
    pool.add(pool.size(), request);
    pool.notifyAll();
    }

  }  
  
  public void run() {
      
    // for security checks
    String root = documentRootDirectory.getPath();
    
    while (true) {   
    Socket connection;
    synchronized (pool) {      
      while (pool.isEmpty()) {
        try {
        pool.wait();
        }
        catch (InterruptedException e) {
        }
      }
      connection = (Socket) pool.remove(0); 
    }

    try {       
      String filename;
      String contentType;   
      OutputStream raw = new BufferedOutputStream(
                    connection.getOutputStream()
                   );      
      Writer out = new OutputStreamWriter(raw);
      Reader in = new InputStreamReader(
               new BufferedInputStream(
                connection.getInputStream()
               ),"ASCII"
              );
      StringBuffer requestLine = new StringBuffer();
      int c;
      while (true) {
        c = in.read();
        if (c == '\r' || c == '\n') break;
        requestLine.append((char) c);
      }
      
      String get = requestLine.toString();
      
      // log the request 
      System.out.println(get);
      
      StringTokenizer st = new StringTokenizer(get);
      String method = st.nextToken();
      String version = "";
      if (method.equals("GET")) {
        filename = st.nextToken();
        if (filename.endsWith("/")) filename += indexFileName;
        contentType = guessContentTypeFromName(filename);
        if (st.hasMoreTokens()) {
        version = st.nextToken();
        }

        File theFile = new File(documentRootDirectory, 
         filename.substring(1,filename.length()));
        if (theFile.canRead() 
          // Don't let clients outside the document root
         && theFile.getCanonicalPath().startsWith(root)) {
        DataInputStream fis = new DataInputStream(
                         new BufferedInputStream(
                        new FileInputStream(theFile)
                         )
                        );
        byte[] theData = new byte[(int) theFile.length()];
        fis.readFully(theData);
        fis.close();
        if (version.startsWith("HTTP/")) {  // send a MIME header
          out.write("HTTP/1.0 200 OK\r\n");
          Date now = new Date();
          out.write("Date: " + now + "\r\n");
          out.write("Server: JHTTP 1.0\r\n");
          out.write("Content-length: " + theData.length + "\r\n");
          out.write("Content-type: " + contentType + "\r\n\r\n");
          out.flush();
        }  // end try
      
        // send the file; it may be an image or other binary data 
        // so use the underlying output stream 
        // instead of the writer
        raw.write(theData);
        raw.flush();
        }  // end if
        else {  // can't find the file
        if (version.startsWith("HTTP/")) {  // send a MIME header
          out.write("HTTP/1.0 404 File Not Found\r\n");
          Date now = new Date();
          out.write("Date: " + now + "\r\n");
          out.write("Server: JHTTP 1.0\r\n");
          out.write("Content-type: text/html\r\n\r\n");
        } 
        out.write("<HTML>\r\n");
        out.write("<HEAD><TITLE>File Not Found</TITLE>\r\n");
        out.write("</HEAD>\r\n");
        out.write("<BODY>");
        out.write("<H1>HTTP Error 404: File Not Found</H1>\r\n");
        out.write("</BODY></HTML>\r\n");
        out.flush();
        }
      }
      else {  // method does not equal "GET"
        if (version.startsWith("HTTP/")) {  // send a MIME header
        out.write("HTTP/1.0 501 Not Implemented\r\n");
        Date now = new Date();
        out.write("Date: " + now + "\r\n");
        out.write("Server: JHTTP 1.0\r\n");
        out.write("Content-type: text/html\r\n\r\n"); 
        }    
        out.write("<HTML>\r\n");
        out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n");
        out.write("</HEAD>\r\n");
        out.write("<BODY>");
        out.write("<H1>HTTP Error 501: Not Implemented</H1>\r\n");
        out.write("</BODY></HTML>\r\n");
        out.flush();
      }
    }
    catch (IOException e) {
    }
    finally {
      try {
        connection.close();   
      }
      catch (IOException e) {} 
    }
    
    } // end while

  } // end run

  public static String guessContentTypeFromName(String name) {
    if (name.endsWith(".html") || name.endsWith(".htm")) {
    return "text/html";
    }
    else if (name.endsWith(".txt") || name.endsWith(".java")) {
    return "text/plain";
    }
    else if (name.endsWith(".gif")) {
    return "image/gif";
    }
    else if (name.endsWith(".class")) {
    return "application/octet-stream";
    }
    else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
    return "image/jpeg";
    }
    else return "text/plain";
  }  

} // end RequestProcessor

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Als je het echt state-of-the-art wilt hebben kan je dit eens doorkijken:

New I/0 Functionality for Java 2 Standard Edition 1.4

Zie de sectie "Non-Blocking Servers" helemaal onderaan. Uiteraard is de rest ook nuttige stuff :) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
*Zucht* Heb je hem weer ;) :P

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: Heb je hem weer ;) :P
Ik heb het zelf eerlijk gezegd nog nergens gebruikt :o . Zelf ben ik dus niet zo state-of-the-art bezig ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
't Enige nadeel van al dat nieuws is dat de SDK/JRE download steeds groter wordt. :P

  • tomato
  • Registratie: November 1999
  • Niet online
Op dinsdag 15 januari 2002 02:09 schreef The - DDD het volgende:
't Enige nadeel van al dat nieuws is dat de SDK/JRE download steeds groter wordt. :P
Mwah, de binary download van 1.4 Beta 3 SDK is nog geen 2 MB meer dan die van 1.3.1 :z

[edit]
Iets zegt me trouwens dat jij deze opmerking al eens eerder maakte (en dat mbravenboer vervolgens zei dat het wel mee viel en met getallen kwam), of zit ik nu te dromen ofzo :?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
En dan krijg je erbij:

* XML parser
* XSLT engine
* Java Web Start
* Nieuwe print library
* Nieuwe IO API's
* Betere MS Windows Look and Feel
* Serieuze cryptografie: JSSE
* Reguliere expressies
* Preferences API

en dan heb ik nog geeneens mijn best gedaan om alles te noemen :+ .

Ik zou ervoor gaan als het maar 2 mb kost ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
tomato: Iets zegt me trouwens dat jij deze opmerking al eens eerder maakte (en dat mbravenboer vervolgens zei dat het wel mee viel en met getallen kwam), of zit ik nu te dromen ofzo :?
Dat ging over de Java 2 Runtime Environment volgens mij (maar was ook iemand anders dacht ik...). Die wordt altijd heel groot ingeschat terwijl dat best meevalt. Zal het weer ff opzoeken:
Java(TM) 2 Runtime Environment, Standard Edition, Beta 3 1.4.0

The download size of the file j2re-1_4_0-beta3-win-i.exe = 11,986,048 bytes.
You have chosen to download Java(TM) 2 Runtime Environment, Standard Edition 1.3.1_02

The download size of the file j2re-1_3_1_02-win-i.exe = 9,047,136 bytes
De J2RE werd toen door iemand ingeschat op 20 mb...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • tomato
  • Registratie: November 1999
  • Niet online
mbravenboer herinnert het zich nog goed
Yep, je hebt gelijk, mijn geheugen is wat gefragmenteerd en bepaalde delen zijn af en toe wat lastig te alloceren.

Maar nu herinner ik het mij weer :)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
tomato: Yep, je hebt gelijk, mijn geheugen is wat gefragmenteerd en bepaalde delen zijn af en toe wat lastig te alloceren.
Matig OS draai je ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • tomato
  • Registratie: November 1999
  • Niet online
mbravenboer: Matig OS draai je ;) .
Krijg de laatste tijd wel veel aanwijzingen door dat ik iets anders moet kiezen met booten :(

Hoe zit het trouwens met Eurocompatibiliteit in Linux? :+

Moet trouwens even IRC client installeren nu...
code:
1
2
3
4
<method-call object="this">
   <method>destructor</method>
   <reason>This thread is getting way too off-topic</reason>
</method-call>

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
tomato: Hoe zit het trouwens met Eurocompatibiliteit in Linux? :+
Geen idee eigenlijk :o . Ik doe niet aan de euro ;) .
Onder Java schijnt het goed te werken >:) .
Moet trouwens even IRC client installeren nu...
Hum, anders mail ik het wel ff ?

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • tomato
  • Registratie: November 1999
  • Niet online
mbravenboer: Hum, anders mail ik het wel ff ?
Is ook goed, ben trouwens je berichtje kwijt en dus ook waar je ergens uithangt op IRC :o |:(

(je kunt dat ook opnieuw sturen...)

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Op dinsdag 15 januari 2002 02:09 schreef The - DDD het volgende:
't Enige nadeel van al dat nieuws is dat de SDK/JRE download steeds groter wordt. :P
Ik heb een beest van een pc hier staan puur voor java, so who cares :)

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op dinsdag 15 januari 2002 10:02 schreef Alarmnummer het volgende:

[..]

Ik heb een beest van een pc hier staan puur voor java, so who cares :)
Ikke, want ik heb een mager ISDN lijntje... :P
Ben met een download van een 15 MB toch zo 2 uur zoet.

En Martin (tha Java Man (ok 1 van de)) komt vaak met een aanvulling, verbetering etc. op posts van mij, dus vandaar dat ik wel vaker zeg: "Heb je hem weer. :P " Maar dit is natuurlijk vriendelijk en eerder nog complimenteus bedoeld.

/me - DDD heeft nu net een mega grote veer in Martins achterste geschoven.
Zo daar mag tie trots op zijn. >:)

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
The - DDD: The - DDD heeft nu net een mega grote veer in Martins achterste geschoven.
Ik voelde het offline al kietelen ;) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment

Pagina: 1