Сървъри и клиенти

сървър - слуша мрежата и очаква клиент да подаде заявка за свързване.Понятие свързано със програма а не с машина.
клиент - подава заявка към сървъра за установяване на връзка.
 

Sockets и ports

port - цяло число от тип  "int", софтуерна абстракция, второ ниво на адресиране в една машина за идентифициране  на програмата сървър съответстваща на осигуряваната услуга (service). Портовете  1 - 1024 са резервирани за стандартни услуги.
Всяка програма сървър е свързана със свой собствен порт. 

socket - софтуерна абстракция за представяне на двата "терминала" за връзка между машините.
    ServerSocket - свързва програмата сървър със съответния порт, слуша мрежата.
    Socket - използван от програмата клиент за свързване със сървъра и обмен на информация. Използвана от програмата сървър за обмен на информация след установяването на връзка.

процедури в програмата сървър:

процедури в програмата клиент:

Пример 1:Клиент за изпращане по SMTP протокол

Стандартът за SMTP протокол се описва от RFC 821. Примерен диалог, който трябва да се води съгласно  RFC 821:

        
         S: MAIL FROM:<Smith@Alpha.ARPA>
         R: 250 OK

         S: RCPT TO:<Jones@Beta.ARPA>
         R: 250 OK

         S: RCPT TO:<Green@Beta.ARPA>
         R: 550 No such user here

         S: RCPT TO:<Brown@Beta.ARPA>
         R: 250 OK

         S: DATA
         R: 354 Start mail input; end with <CRLF>.<CRLF>
         S: Date: 23 Oct 81 11:22:33
         S: From: Smith@Alpha.ARPA
         S: To: Jones@Beta.ARPA,Green@Beta.ARPA,Brown@Beta.ARPA
         S: Subject: Mail System Problem
         S:
         S:   Bla..Bla..
         S:   Bla..Bla
         S:   Bla..
         S: .
         R: 250 ok
 
         The mail has now been accepted for Jones and Brown.  Green did
         not have a mailbox at host Beta.
         

Всеки ред трябва да завършва с <CRLF> комбинация. В горния пример съобщението е прието за Jones и  Brown.  Green няма пощенска кутия в този сървър. Редовете:

         S: Date: 23 Oct 81 11:22:33
         S: From: Smith@Alpha.ARPA
         S: To: Jones@Beta.ARPA,Green@Beta.ARPA,Brown@Beta.ARPA
         S: Subject: Mail System Problem

задават "header" на съобщението и не са задължителни.

Отваряне и затваряне

      Преди обмена на информацията се отваря трансмисионен канал за обмен на информацията за изпращача и сървъра.

      Използват се следните две команди за отваряне и затваряне

         HELO <SP> <domain> <CRLF>

         QUIT <CRLF>

      С командата HELO изпращащата машина се идентифицира казвайки:
      "Hello, I am  <domain>".

 

Клиентът:

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

public class MailSend{
	private static String messageSys[]= new String[4],
	               messageData[]=new String[5],hostName=null;
	private static InetAddress mServer= null;
	public static void init(){
		int j=0;
		try{
			mServer=InetAddress.getByName("myMailServer.bg");
			hostName= InetAddress.getLocalHost().getHostName();
		}catch(Exception e){System.out.println("Exception"+e);}
		
		messageSys[0]="HELO "+hostName+"\r\n";
		messageSys[1]="MAIL FROM: <myName@myDomain.bg>\r\n";
		messageSys[2]="RCPT TO: ";
		messageSys[3]="DATA\r\n";
		messageData[0]="From: myName@myDomain.bg"+"\r\n";
		messageData[1]="To:";
		messageData[2]="Subject: ";
		messageData[3]= "";
		messageData[4]=".\r\n";

	}
	public static void putData(String arg[]){
		messageSys[2]+=arg[0]+"\r\n";
		messageData[1]+=arg[0]+"\r\n";
		messageData[2]+= arg[1]+"\r\n";
		messageData[3]= arg[2]+"\r\n";
		
	}
	public static void send (){
		try{                                 // или c timeout 10000 ms:
		        Socket s=null;		    // Socket s = new Socket();	
			s = new Socket(mServer,25);  // s.connect(new InetSocketAddress(
                                                     //    mserver,25),10000);
			BufferedReader in = new BufferedReader(
                    new InputStreamReader(s.getInputStream()));
			PrintWriter out = new PrintWriter(s.getOutputStream());
			System.out.println(in.readLine());
			for(int i=0; i<messageSys.length;i++){
				out.print(messageSys[i]);
				System.out.println(messageSys[i]);
				out.flush();
				System.out.println(in.readLine());
			}
			for(int i=0;i<messageData.length;i++){
				out.print(messageData[i]);
				System.out.println(messageData[i]);
				out.flush();
			}
			System.out.println(in.readLine());
			s.close();
		}
		 catch(Exception e) {System.out.println(e); }
	} 
}

и съответния интерфейс:

import java.awt.*;
import java.awt.event.*;

class Gui{
	TextArea ta;
	TextField sb,to;
	Label ls,lt;
	Button send;
	Panel p= new Panel();
	Gui(Frame f){
		ta = new TextArea(10,20);
		send = new Button("send");
		to = new TextField("",20);
		lt= new Label("To:");
		sb = new TextField("",20);
		ls = new Label("Subject:");
		send.addActionListener(new S());
		p.add(lt);
		p.add(to);
		p.add(ls);
		p.add(sb);
		f.add(p,BorderLayout.NORTH);
		f.add(ta, BorderLayout.CENTER);
		f.add(send, BorderLayout.SOUTH);
		MailSend.init();
	}
	class S implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			String message[]= {to.getText(),sb.getText(),ta.getText()};
			MailSend.putData(message);
			MailSend.send();
		}
	}
	static class WL extends WindowAdapter { 
	    public void windowClosing(WindowEvent e) { 
	    	System.exit(0); 
	    } 
	} 


	public static void main(String args[]){
		Frame frame =new Frame("Mail Sender");
		Gui gui = new Gui(frame);
		frame.setSize(500,300);
		frame.addWindowListener(new WL()); 
		frame.setVisible(true);
	}
}

Задача: Въведете в интерфейса съобщения при неуспешно изпращане

Пример 2:Един прост сървър и клиент:


// FirstServer.java
// Very simple server that just
// echoes whatever the client sends.
import java.io.*;
import java.net.*;

public class FirstServer {
  // Choose a port outside of the range 1-1024:
  public static final int PORT = 8080;
  public static void main(String[] args)
      throws IOException {
    ServerSocket s = new ServerSocket(PORT);   
    System.out.println("Started: " + s);
    try {
      // Blocks until a connection occurs:
      Socket socket = s.accept();                                           
      try {                                                                                //
        System.out.println(
          "Connection accepted: "+ socket);
        BufferedReader in =
          new BufferedReader(
            new InputStreamReader(
              socket.getInputStream()));
        // Output is automatically flushed
        // by PrintWriter:
        PrintWriter out =
          new PrintWriter(
            new BufferedWriter(
              new OutputStreamWriter(
                socket.getOutputStream())),true);
        while (true) {
          String str = in.readLine();
          if (str.equals("END")) break;
          System.out.println("Echoing: " + str);
          out.println(str);
        }
      // Always close the two sockets...
      } finally {
        System.out.println("closing...");
        socket.close();
      }
    } finally {
      s.close();
    }
  }
}

 


//Very simple client that just sends 
//lines to the server and reads lines 
//that the server sends. 
import java.net.*; 
import java.io.*; 
public class FirstClient { 
   public static void main(String[] args)throws IOException { 
	// Passing null to getByName() produces the 
	 // special "Local Loopback" IP address, for 
	 // testing on one machine w/o a network: 
	 // Alternatively, you can use 
	 // the address or name: 
	 // InetAddress addr = InetAddress.getByName("127.0.0.1"); 
	 // InetAddress addr = InetAddress.getByName("localhost"); 
	 String server = null; 
	 InetAddress addr =  InetAddress.getByName(server); 
	 System.out.println("addr = " + addr); 
	 Socket socket = new Socket(addr, FirstServer.PORT);                       //Socket s=new Socket();
	 // Guard everything in a try-finally to make                                         //s.connect(new  InetSocketAddress(host,port),timeout); 
	 // sure that the socket is closed: 
	 try { 
	      System.out.println("socket = " + socket); 
	      BufferedReader in = 
	          new BufferedReader( 
	            new InputStreamReader(socket.getInputStream())); 
	      BufferedReader sin =  new BufferedReader( 
	            new InputStreamReader(System.in)); 
		   
	      // Output is automatically flushed 
	      // by PrintWriter: 
	     PrintWriter out =   new PrintWriter( 
	            new BufferedWriter(  new OutputStreamWriter( 
		           socket.getOutputStream())),true); 
	     for(int i = 0; i <10 ; i ++) { 
	         System.out.print("input a line [empty for finish] " + i + ":"); 
	         String s = sin.readLine(); 
	          if(s.length()==0) break; 
	         out.println(i + ": " +s); 
	         String str = in.readLine(); 
	         System.out.println(str); 
	     } 
	     out.println("END"); 
                 } 
	 finally { 
		   System.out.println("closing..."); 
		   socket.close(); 
	 } 
       } 
} 


резултати:
 
>java FirstServer
Started: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=8080]
Connection accepted: Socket[addr=127.0.0.1/127.0.0.1,port=1029,localport=8080]
Echoing: first line   :0
Echoing: second line   :1
Echoing: third line   :2
closing...
>java FirstClient
addr = localhost/127.0.0.1
socket = Socket[addr=localhost/127.0.0.1,port=8080,localport=1033]
input a line [empty for finish] 0:
first line   :0
input a line [empty for finish] 1:
second line   :1
input a line [empty for finish] 2:
third line   :2
input a line [empty for finish] 3:
closing...

 

Обслужване на повече от един клиент

Налага се използването на отделна нишка за всеки клиент:

//: MultiClientServer.java
// A server that uses multithreading to handle
// any number of clients.
import java.io.*;
import java.net.*;

class ServeOneClient extends Thread {
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    public ServeOneClient(Socket s)  throws IOException {
        socket = s;
        in = new BufferedReader(
                new InputStreamReader(
                  socket.getInputStream()));
    // Enable auto-flush:
        out = new PrintWriter( new BufferedWriter(
                                                   new OutputStreamWriter(
                                                     socket.getOutputStream()
                                                   )
                                              ),
                  true);
    // If any of the above calls throw an
    // exception, the caller is responsible for
    // closing the socket. Otherwise the thread
    // will close it.
        start();    // Calls run()
  }
  public void run() {
    try {
        while (true) {
             String str = in.readLine();
             if (str.equals("END")) break;
            System.out.println("Echoing: " + str);
            out.println(str);
        }
        System.out.println("closing...");
    } catch (IOException e) {  }
   finally {
      try {
        socket.close();
      } catch(IOException e) {}
    }
  }
}

public class MultiClientServer {
  static final int PORT = 8080;
  public static void main(String[] args) throws IOException {
    ServerSocket s = new ServerSocket(PORT);
    System.out.println("Server Started");
    try {
      while(true) {
        // Blocks until a connection occurs:
        Socket socket = s.accept();
        try {
          new ServeOneClient(socket);
        } catch(IOException e) {
          // If it fails, close the socket,
          // otherwise the thread will close it:
          socket.close();
        }
      }
    } finally {
      s.close();
    }
  }
}

 

Клиенти с име:

// Client with name
import java.net.*;
import java.io.*;

public class ClientWithName {
   public static void main(String[] args)throws IOException {
   // Passing null to getByName() produces the
    // special "Local Loopback" IP address, for
    // testing on one machine w/o a network:
    // Alternatively, you can use
    // the address or name:
    // InetAddress addr = InetAddress.getByName("127.0.0.1");
    // InetAddress addr = InetAddress.getByName("localhost");

        String serveur = null;
    InetAddress addr = InetAddress.getByName(serveur);
    System.out.println("addr = " + addr);
    Socket socket = new Socket(addr, FirstServer.PORT);
    // Guard everything in a try-finally to make
    // sure that the socket is closed:
        try {
            System.out.println("socket = " + socket);
             BufferedReader sin = new BufferedReader(
                      new InputStreamReader(System.in));
            BufferedReader in =  new BufferedReader(
                  new InputStreamReader(socket.getInputStream()));
            // Output is automatically flushed
            // by PrintWriter:
            PrintWriter out = new PrintWriter(new BufferedWriter(
                      new OutputStreamWriter(socket.getOutputStream())),true);
            System.out.print("Your name: ");
            String name = sin.readLine();
            for(int i = 0; i <10 ; i ++) {
                System.out.println("input a line [empty for finish] :");
                String s = sin.readLine();
                if(s.length()==0) break;
                out.println(name+":"+s);
               String str = in.readLine();
               System.out.println(str);
           }
           out.println("END");
        } finally {
                System.out.println("closing...");
                socket.close();
        }
   }