Hi Dw

I'm trying to create a server that will handle simultaneous connections from clients and for simplicity I've decided to save data to the text files, it not one text file but there are many text files which will be located on the server.

The clients (written in VB5.0) will connect to the server only when a user has clicked join button. I have almost more then 57 buttons which are choices a user will select only one button. I will make an example with the first two buttons. Button1 'Cow' , Button2 'Dog'.

Now the client will send this info to the server suppose the user clicked Button1 which is Dog so the message that will be sent to the server will be "Cow, 1, Area"

'Cow' is to tell the server the name of a text file to write in the '1' and the 'Area' will be retrieved by the client on a configuration file which will be located on each client computer but the area will also be used too. Now that I've said that let me break it down to what I have and what I'm trying to do.

On the server I will have folders that will be located in drive 'C:\' the folder structure will be as follows "Date&Year "-> inside I will have two folders: first; on this folder inside it I will have empty text files which will be updated by the server as clients make their selections and each text file will be named as the Clients buttons like "Cow", "Dog" so that if the client sends a message starting with "Cow" the server will know that it should put '1' inside the Cow.txt file on each line and on the second folder I will have 9 folders inside each folder will be named with the province name and inside these 9 folders on each folder I will have the same and equal text files as in folder 1 which are more then 57 text files.

For the second folder the server will get the message from the client as follows "Folder2, Area, Dog, 1" and the server should be able to open folder2 and select the correct province as the Area and locate text file Dog and inside it insert '1'.

My problem is starting the creation of this server, I've looked to some servers but they are for chatting but this is a different scenario and I don't know how I'm going to split the client message so that I can determine which folder to open, which province to open , and which text file to add 1 to, and also there can be almost 10 or higher clients that may send the same request or message at the same time to the server that means each text file will be updated while another thread is updating it so as I'm working with text file I don't know if this can happen.

I've change from Visual Basic because the multithread is a bit a problem with VB and there is no much resources.

I've forgot to mention the connection to the server from client will always be close will only be open once a user click connect or join button then the user will make the choice and the message will be sent the first message goes to the first folder and the client program will display another choice panel for the user to make another selection then the client will send the second message which is for the second folder. First and second message format:
First message: "Cow, 1"
Second message: "Folder2, Area, Cow, 1"
Folder2 will be the name of folder 2. The above was the assumption that a user chose Cow on client side.

Thank you.

Recommended Answers

All 13 Replies

  1. Multi-threaded server for multiple concurrent clients: see
    http://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html (don't miss the bit about multiple clients towards the end)
  2. Splitting the message - just use String's split method. If that's not good enough then search for delimiters with indexOf the use substring to pick it apart.
  3. Concurrent update of files: use synchronised with a suitable lock object to serialise multiple threads' access to files.

Thank you, but I couldn't get it working using that link, it had bugs and I didn't understand some parts like the "KnockKnockProtocol" so I just started by making a single thread or app to accept the connection from a VB 5.0 app client which it does accept connection but now the problem is that if the client send the data to the server the server does not print it out until on the client I close the Winsock connection (Winsock1.Close) then the server prints the data that was sent by a client. Any idea why it can't print immediately just like my other server I created using VB5.0?

I used the tutorial on the following post:
<a href="http://www.dreamincode.net/forums/topic/38672-creating-a-server-to-serve-clients/">here is it</a>

And also about splitting the received message so that I can put the correct data into their corresponding files can you give me a sample suppose the client sends:
(Cow, 1, Moscow)

Cow as the name of the file and
1 as the value which will be written to the file and
Moscow as the place which will also the name of a folder containing the file Cow.

Thanks again.

The Oracle tutorial had bugs? I doubt it.
What you are trying to do isn't so simple, so you will need to understand everything in that tutorial, no matter how much effort that may take.

Maybe the message that the client sends does not have a newline character at the end?

String[] tokens = "Cow, 1, Moscow".split(","); should give you a three element array {"Cow", " 1", " Moscow"} from which you can pick out the elements, eg
String place = tokens[2].trim();

Just a little improvement on split function. You could use the regex pattern as split("\\s*,\\s*") and that would handle any white spaces around the comma. As a result, you do not need to trim() on each token later on.

Ok thanks but I haven't tried those suggestions yet. I can see that I didn't fully mentioned the message format now by looking on both of your posts I can see that if I don't state now the changes I made to the message format I will have a serious problem.

Well I will only show how I formatted the message or how it is displayed on the server before we get to the part of separating or splitting it into pieces.

First of all let me clear out about the message it self. The client sends a two messages not two separate messages but it one message which has 2 messages. This may not be clear till I show you the message, I won't show the client but I will show the output. Here is the message

Suppose the client is at Moscow, the client's first choice is Cow and also his/her second choice is Cow and the year is 2014. The messages are as follow note that the client make two choices before the socket sends the message to the server.

The message display as shown below:

< 2014 , N , Cow , 1 > < 2014 , Moscow , Cow , 1 >

As you can see above this is a 1 message received and it contains two messages.
The first message is < 2014 , N , Cow , 1 > which when being split the server will use it to locate the folder named 2014 and inside it, it will locate another folder named N and inside the N folder it will locate the text file named Cow.txt and it will write the value 1 on that file. Same thing with the second potion of the message.

Is it possible to split one message in to two messages and split each splitted messages to get or break down or separate each data on each message as each data is a clue to a server as I've braked down the first potion of the message using either of the samples you provided?

I think it will be much better if each data on the splitted message gets it own variable on the server like 'fYear' which will hold the 2014 data, 'fStatus' which will hold N data, 'fFile' which will hold or be assigned with Cow of the first message, 'fValue' for the first message value. I putted the 'f' to indicate that it for the first potion of the message the second potion variables will start with 's' for second e.g. 'sYear', 'sStatus' etc.

Thank you again.

Yes, you could. Simply use split more than one time. See below example.

// i.e.
// assumption: each message will be enclosed inside < and >
String sample = " <2014,N , Cow ,1>  <2014 , Moscow, Cow , 1> ";
// .trim() is to trim the incoming message just in case,
// .replaceFirst("^<","") is to remove leading <
// .replaceFirst(">$","") is to remove tailing >
// .split(regex) will handles any whitespaces in between just in case
String[] messages = sample.trim().replaceFirst("^<","").replaceFirst(">$","").split("\\s*>\\s*<\\s*");
for (String message : messages) {
  System.out.println("Message: "+message);
  String[] data = message.split("\\s*,\\s*");
  for (String dat : data) { System.out.println("~~"+dat+"~~); }
}

You could also use matching to pick each portion right away, but it would require a little bit deeper in regex.

Wow!!! That was awesome. Thank you in a million ways. Excellent and I doubt I was goner be able to write that. Impressive.

Thank you soo much that was purely clean and excellent. Now how will I initialize these values to each variable?

Also I've added trim at "String[] data = message.split("\s,\s"); because the last value of the second potion was having a space at th end like this ~~1 ~~ after I've added trim before "split()" like this message.trim().split ".

Thanks again

Thanks I've sorted it out. Thanks to each and everyone of you who participated.

Oops another problem arise.
I've used "fChoice = data[1];" to pick the first potion users Choice, but the problem is that its a loop so the variable "fChoice" only holds the value for the first potion while the loop is there or while the system is reading there once the system moves on to read the second potion, this fChoice variable clears the first potion value and holds the second potion value.

Note that the values or data on array[1] in both potions are not the same. The first potion data[1] holds the users choice, and the second portion data[1] holds the province

I have fChoice variable which should only holds the first potion data[1] value and the sProvince variable should only holds the second potion data[1] value.

Any suggestion on how I can solve this?

Thanks again

I've just took an advantage of it and written the value to the corresponding file while the fChoice variable holds the values. One variable is able to locate two different folders that contains the same file and write to it. Thanks it working fine now.

The problem is that when ever the client closes it connection to the server the server shutsdown. Any idea how can I solve that?

Use a multi-thread client handler as per the Oracle tutorial! Then the client can do wahtever it likes without upsetting the thread where the server socket is listening.
Maybe this sample code will help you understand the structure...

public class SimplestServer implements Runnable {
   // simple demo of server for multiple clients (eg chat room)
   // sends "hello" message then echoes any input from client
   //
   // NB: This demo has no real error handling or shutdown/cleanup logic - 
   // you have to crash both client and server to stop it.
   // a real application will need an appropriate solid implementation

   public static void main(String[] args) {
      new SimplestServer(999).start();
   }

   private ServerSocket serverSocket;

   public SimplestServer(int port) {
      try { // Create the server socket
         serverSocket = new ServerSocket(port);
      } catch (IOException e) {
         System.out.println("Server couldn't open listen socket on port " + port + "\n" + e);
      }
   }

   public void start() {
      new Thread(this).start();
   }

   @Override
   public void run() {
      try {
         System.out.println("Server is listening");
         while (true) {
            Socket clientSocket = serverSocket.accept();
            System.out.println("Connect from: " + clientSocket);
            new Thread(new ClientInterface(clientSocket)).start();
         }
      } catch (IOException e) {
         e.printStackTrace();
      }
      // shutdown and tidy-up logic (logoff sockets etc) omitted for clarity
   }

   private class ClientInterface implements Runnable {
      // starts a thread to wait for and process input from the client
      // also provides a sendOutput method to send stuff to the client any time

      private final BufferedReader inbound; 
      private final PrintWriter outbound;

      public ClientInterface(Socket clientSocket) throws IOException {
         inbound = new BufferedReader(new InputStreamReader(
                 clientSocket.getInputStream()));
         outbound = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                 clientSocket.getOutputStream())), true); // autoflush
         outbound.println("You are now connected to the server");
      }

      @Override
      public void run() {
         try {
            String input;
            while ((input = inbound.readLine()) != null) {
               System.out.println("Server received " + input);
               sendOutput("Echo: " + input); // echo to client
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
         // shutdown and tidy-up logic (logoff streams etc) omitted for clarity
      }

      public void sendOutput(String output) {
         // (can be called any time, not only in response to input from client)
         System.out.println("Server sending " + output);
         outbound.println(output);
      }
   }
}

Thanks that helped a lot. I was going to ask this question later but then since you have brought this forward I will just ask straight away.

What I wanted to do was since it a multiple thread and multiple clients are connected simultaneously I wanted the client to get a certain number on a text file which will be generated by another program and that text file is an unlocker of a client system, meaning the components on a client side are hidden so that no user(human) can use the system at the moment till a this text file is created and once it has been created the client will take the text(it a number but I don't treat it as numbers I treat it as text) and it will look on another text file to see if the text(numbers) in the text unlock.txt do match any text(number) in text verify.txt

The text verify.txt get the texts in two ways.
1) The client it self write the text from a text file unlock.txt if the unlock.txt texts doesn't have a match and the client will send out this texts as echo so that all the clients connected will also receive this text and write it on their verify.txt so that this number will not be used twice in any client connected.
2) The client gets the echo from other clients and first it check if the echoed text hasn't already been written to the file verify.txt if it has been written it will just ignore that echo text.

Now how can I do this? The message that is sent by a client which is the previous message which is one massage with two messages inside should not be echoed at all only the text that is for verification that's must be shared and each client should not write twice the same text on a text file line by line.

Assume client 1's verify.txt file has 222151680264 this text(number) should be shared with all clients and suppose the 6th client already has this text on it file the 6th client should tell the 1st client that the text has already been used so that the 1st client won't enable the system because the text was already used.

Is it possible to do that kind of a thing or do I have to make the server be the one who sends and register(write) new texts on it text file and the clients will request the verification from server and the server will send the text "enable" to that requesting client it the text wasn't found and "reject" if the text was found?

If it should be the server won't that affect the service speed of getting the messages from clients and writing texts to their correct files and also on the other side it search's to find out that the texts that was sent but another program do exist on the other side it write the texts that is sent but requesting clients who's texts wasn't found on the file?

And also about terminating the sever.
Thank you

Sorry, no time to digest all that today, but in general...
Your "server" is just a place to accept connections and start a client handler thread for each connection. That's good as it is, don't mess with it.
As you create each client you can add them to a List (or Map<username, client instance>). With that you can get the handler for a different client and send it messages etc. If it gets a more complex create a new class that's responsible for maintaining the list of clients and routing stuff back and forth between them.

Terminating is a bit messy. Basically just close the server socket, then catch and ignore the exception that it throws from the accept() method. Similarly to close a clinet connection - close its socket and ignore the resulting exceptions from the read method.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.