Java Server application

Source: Internet
Author: User
Tags final include mail printf requires socket strcmp trim

Now to discuss the server application (program) problem, I call it Namecollecor (name collector). What happens if multiple users try to submit their e-mail address at the same time? If Namecollector uses TCP/IP sockets, you must use the multithreaded mechanism described earlier to implement concurrency control for multiple customers. But all of these threads are trying to write the data into the same file, where all the e-mail addresses are saved. This requires that we set up a locking mechanism to ensure that multiple threads do not access that file at the same time. A "signal machine" can help us achieve the goal here, but there may be a simpler way.
If we switch datagrams, we don't have to use multithreading. A single datagram can "listen" to all the datagrams entered. Once the incoming message is monitored, the program handles it appropriately and returns the reply data as a datagram back to the recipient who originally made the request. If the datagram is lost halfway, the user will notice that no reply data is returned, so the request can be resubmitted.
When a server application receives a datagram and interprets it, it must extract the e-mail address and check the data file saved by the computer to see if it already contains that address (if not, add it). So now we're having a new problem. Java 1.0 does not seem to have enough capacity to easily process files that contain e-mail addresses (otherwise, Java 1.1). However, it is easy to solve this problem with C. So here we have the opportunity to learn the easiest way to connect a non-Java program to a Java program. The runtime object used by the program contains a method called EXEC () that is independent of a program on the machine, and returns a Process object. We can get a outputstream, which is connected to the standard input of this individual program, and gets a inputstream, which is connected to the standard output. All you have to do is write a program in any language, as long as it gets its input data from the standard input and writes the output to the standard output. Consider this approach if there are problems that cannot be easily and quickly solved in Java (or if you want to take advantage of existing code and do not want to overwrite it). You can also use the Java "intrinsic method" (Native methods), but that requires more skill, and you may refer to Appendix A.

1. C Procedure
This non-Java application is written in C because Java does not cooperate with CGI programming; The minimum startup time is not satisfying. Its task is to manage a list of e-mail addresses. The standard input will accept an e-mail address, and the program will check the name in the list to determine if the address exists. If it does not exist, it is added and the operation is reported successfully. But if the name is already in the list, it needs to be pointed out and avoid repetition. You don't have to worry that you can't fully understand the meaning of the following code. It's just a demo program that tells you how to write a program in other languages and call it from Java. It doesn't matter what language you use here, as long as you can read the data from the standard input and write to the standard output.

: LISTMGR.C//Used by Namecollector.java to manage//The e-mail list file on the server #include <stdio.h> #inc Lude <stdlib.h> #include <string.h> #define Bsize int alreadyinlist (file* list, char* name) {char Lbuf
  [Bsize];
  Go to the beginning of the List:fseek (list, 0, seek_set); Read the List:while (fgets (lbuf, bsize, list)) {//Strip off the Newline:char * newline = strc
    HR (lbuf, ' \ n ');
    if (newline!= 0) *newline = ';
  if (strcmp (lbuf, name) = = 0) return 1;
return 0;
  int main () {char buf[bsize];
  file* list = fopen ("Emlist.txt", "a+t");
    if (list = = 0) {perror ("could not open emlist.txt");
  Exit (1); while (1) {gets (BUF);/* from stdin/if (Alreadyinlist (list, buf)) {printf ("Already in list:%s", buf)
      ;
    Fflush (stdout);
      else {fseek (list, 0, seek_end);
      fprintf (list, "%s\n", buf);
      Fflush (list); printf ("%s added to list", buf);
    Fflush (stdout); }
  }
} ///:~


The program assumes that the C compiler accepts a '//' style annotation (which many compilers can and also uses a C + + compiler to compile the program). If your compiler is not acceptable, simply delete those annotations.
The first function in the file checks whether the name passed to it as the second argument (pointer to a char) is already in the file. Here, we pass the file as a filename pointer, which points to an open file (the file is opened in Main ()). The function fseek () is traversed in the file; we use it here to move to the beginning of the file. Fgets () reads a line from the file list and place it into the buffer lbuf--does not exceed the specified buffer length bsize. All of this work is done in a while loop, so each row in the file is read. Next, find the new line character with STRCHR () to delete it. Finally, use strcmp () to compare the names we pass to the function and the current line in the file. If a consistent content is found, strcmp () returns 0. The function then exits and returns a 1, stating that the name is already in the file (note that the function returns immediately after finding the match, and does not waste time on checking the remainder of the list). If the list does not find a match, the function returns 0.
In main (), we open the file with fopen (). The first parameter is the file name, the second is the way the file is opened, A + is "append", and "open" (or "create", if the file does not already exist) to be updated at the end of the file. The fopen () function returns a file pointer, or 0, which indicates that the open operation failed. At this point you need to print an error message with perror () and abort the program with exit ().
If the file is successfully opened, the program will enter an infinite loop. Functions that call gets (BUF) take one row out of the standard input (remember that standard input is connected to the Java program) and put it into the buffer buf. The contents of the buffer are then simply passed to the alreadyinlist () function, as the content is already in the list, and printf () sends that message to standard output (the Java program is monitoring it). Fflush () is used to refresh the output buffer.
If the name is not in the list, move to the end of the list with fseek () and fprintf () to "print" the name to the end of the list. Then, using printf () to indicate that the name has been successfully added to the list (also need to refresh the standard output), the infinite Loop returns, and continues to wait for a new name to enter.
Remember that you generally cannot compile this program on your own computer before uploading the compiled content to a Web server, because that machine may be using different classes of processors and operating systems. For example, my Web server is installed with Intel's CPU, but the operating system is Linux, so you must first download the source code, and then use Remote command (via Telnet) to direct the Linux with the C compiler, so that it compiles a good program on the server side.

2. Java programs
The program starts the above C program and then establishes the necessary connection to "talk" to it. It then creates a datagram socket that uses it to "monitor" or "listen" to a datagram package from a program slice.

: Namecollector.java//Extracts email names from datagrams and stores//them inside a file, using Java 1.02.
Import java.net.*;
Import java.io.*;

Import java.util.*;
  public class Namecollector {final static int collector_port = 8080;
  Final static int buffer_size = 1000;
  byte[] buf = new Byte[buffer_size];
  Datagrampacket DP = new Datagrampacket (buf, buf.length);
  Can Listen & Send on the same socket:datagramsocket socket;
  Process Listmgr;
  PrintStream NameList;
  DataInputStream Addresult;
      Public Namecollector () {try {listmgr = Runtime.getruntime (). EXEC ("Listmgr.exe");
      NameList = new PrintStream (New Bufferedoutputstream (Listmgr.getoutputstream ()));

    Addresult = new DataInputStream (New Bufferedinputstream (Listmgr.getinputstream ()));
      catch (IOException e) {System.err.println ("Cannot start Listmgr.exe");
    System.exit (1);
      try {socket =  New Datagramsocket (Collector_port);
      System.out.println ("Namecollector Server started");
        while (true) {//block until a datagram Appears:socket.receive (DP);
        String rcvd = new String (Dp.getdata (), 0, 0, dp.getlength ());
        Send to Listmgr.exe Standard Input:nameList.println (Rcvd.trim ());
        Namelist.flush ();
        byte[] Resultbuf = new Byte[buffer_size];
        int byteCount = Addresult.read (RESULTBUF);
          if (ByteCount!=-1) {String result = new String (resultbuf, 0). Trim (); Extract the "address" and "Port From//" received datagram to find out/where to send the reply
          : inetaddress senderaddress = dp.getaddress ();
          int senderport = Dp.getport ();
          byte[] Echobuf = new Byte[buffer_size];
          Result.getbytes (0, ByteCount, echobuf, 0);
      Datagrampacket echo =      New Datagrampacket (Echobuf, Echobuf.length, senderaddress, Senderport);
        Socket.send (Echo);
      else System.out.println ("Unexpected lack of result" + "Listmgr.exe");
      The catch (SocketException e) {System.err.println ("Can ' t Open socket");
    System.exit (1);
      catch (IOException e) {System.err.println ("Communication error");
    E.printstacktrace ();
  } public static void Main (string[] args) {new Namecollector (); }
} ///:~


The first definition in Namecollector should be familiar: Select the port, create a datagram package, and then create a handle to a datagramsocket. The next three definitions are responsible for connecting to the C program: A Process object is returned by a Java program, and the process object produces InputStream and OutputStream, representing the standard output and standard input of the C program, respectively. Like Java io, they naturally need to be "encapsulated", so we end up with a printstream and DataInputStream.
All the work of this program is done in the builder. To start the C program, you need to get the current runtime object. We use it to invoke exec (), which returns the Process object. In the Process object, you can see that the data flow is generated by a simple call: Getoutputstream () and getInputStream (). From this point on, all we need to think about is to pass the data to the data stream namelist and get the results from the Addresult.
As always, we connect the datagramsocket to the same port. In an infinite while loop, the program invokes receive ()--unless a datagram arrives, receive () is stuck together in a "blocked" state. After the datagram appears, its contents are extracted into string rcvd. We first remove the space (trim) from both ends of the string and send it to the C program. As shown below:
Namelist.println (Rcvd.trim ());
The reason for this encoding is that Java exec () allows us to access any executable module, as long as it can be read from the standard input and be able to write to the standard output. There are other ways to "talk" to non-Java code, which will be discussed in Appendix A.
Capturing results from a C program can be a bit of a hassle. We must call read () and provide a buffer to save the results. The return value of Read () is the number of bytes from the C program. If this value is-1, it means that there is a problem somewhere. Otherwise, we convert the Resultbuf (result buffer) to a string, and then remove the extra spaces as well. The string then goes into a datagrampacket as usual and returns the same address as the original one that made the request. Note that the sender's address is also part of the datagrampacket we received.
Remember that although a C program must be compiled on a Web server, the compilation site of a Java program can be arbitrary. This is because no matter what hardware platform and operating system is used, the compiled bytecode is the same. Is the Java "cross-platform" compatibility capability.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.