Šta je novo?

Socket programiranje Hitno!!

  • Začetnik teme Začetnik teme filipp
  • Datum pokretanja Datum pokretanja

filipp

Čuven
Učlanjen(a)
15.03.2003
Poruke
847
Poena
619
Dakle za faks imam zadatak da napisem Socket aplikaciju (Klient i Server) gde Server kontinuirano radi , tj. moze vise
zahteva jedan za drugim da obradi.

Sa Klijenta dajemo komandu pruzmi<ime fajla>. Server treba da potrazi fajl u svom lokalnom direktorijumu i
da posalje sadrzaj fajla klijentu tj. ispise sadrzaj na ekranu. U pitanju je jednostavan .txt fajl.
Sa komandom Stop klijent signalizira serveru tj. server prestaje sa radom.




Kod:
import java.net.*;
import java.io.*;
public class SimpleServer {
  public static void main(String args[]) throws IOException {
    // Register service on port 1234
    ServerSocket s = new ServerSocket(1234);
    Socket s1=s.accept(); // Wait and accept a connection
    // Get a communication stream associated with the socket
    OutputStream s1out = s1.getOutputStream();
    DataOutputStream dos = new DataOutputStream (s1out);
    // Send a string!
    dos.writeUTF("Hi there");
    // Close the connection, but not the server socket
    dos.close();
    s1out.close();
    s1.close();
  }
}


i klijent


Kod:
import java.net.*;
import java.io.*;
public class SimpleClient {
  public static void main(String args[]) throws IOException {
    // Open your connection to a server, at port 1234
    Socket s1 = new Socket("localhost",1234);
    // Get an input file handle from the socket and read the input
    InputStream s1In = s1.getInputStream();
    DataInputStream dis = new DataInputStream(s1In);
    String st = new String (dis.readUTF());
    System.out.println(st);
    // When done, just close the connection and exit
    dis.close();
    s1In.close();
    s1.close();
  }
}


E sada imam i gotovu klasu ReadFromFile ali mi nije jasno kako da povezem tj. promenim klase Client i Server da
dobijem zeljeni rezultat.
Svaka pomoc dobrodosla!


Kod:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;


public class ReadFromFile {

   
    public static void main(String[] args) {
        ReadFromFile rff=new ReadFromFile();
        rff.readFile();
        
    }
    
    public void readFile()
    {

        File file = new File ("input.txt");

        Scanner scanner = null;
        try {
   
           scanner = new Scanner (file);
        } catch (FileNotFoundException e) {
          System.out.println ("File not found!");
         
          System.exit (0);
        }
   
        while(scanner.hasNext())
        {

            String tmp=scanner.nextLine();

            System.out.println(tmp);
        }
        
    }

}
 
Ajd da pokusam ovako napamet da ti dam kako bi mogao da uradis.. Ovo sto sam ti napisao je klasa ReadFromFile. U klasi server pravis objekat klase read from file, i tu u while petlji citas taj file( scanner) i saljes clientu. Dalje sad kazes da treba server da radi u kontinuitetu? Sa vise klienata? ako ima vise trebao bi sa nitima da radis, sad cu da potrazim jedan primer za javu odakle mozes da izvuces koncepte..
Baci pogled na ovo:
http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html
prouci, slican je princip kao chat server..

Kod:
import java.net.*;
import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;



public class ReadFromFile {

       File file;
     Scanner scanner;
    public ReadFromFile(String f) //konstruktor klase kome prosledjujes ime fajla koga citas.
    {
     file = new File (f);
     scanner = null;
        try {
   
           scanner = new Scanner (file);
        } catch (FileNotFoundException e) {
          System.out.println ("File not found!");
         
          System.exit (0);
        }
   
}
Public Scanner GetScanner(){return scanner;}  //moglo je i da se scanner stavi public, ali profe ne vole to.. :P
}

public class SimpleServer {
 
  public static void main(String args[]) throws IOException {
    // Register service on port 1234
    ServerSocket s = new ServerSocket(1234);
    Socket s1=s.accept(); // Wait and accept a connection
    // Get a communication stream associated with the socket
    OutputStream s1out = s1.getOutputStream();
    DataOutputStream dos = new DataOutputStream (s1out);
 
    ReadFromFile MyFile=new ReadFromFile("input.txt"); //Ovde stavi ime fajla koji citas i saljes
    Scanner scn=MyFile.GetScanner();

while(scn.hasNext())
        {

            String tmp=scanner.nextLine();
               // Send a string!
         dos.writeUTF(tmp);
        }
    // Close the connection, but not the server socket
    dos.close();
    s1out.close();
    s1.close();
  }
}

Nisam proverio da li radi, trebalo bi, mada u principu ako ne radi, uz malo modifikacije sigurno mozes da nateras da radi.. Otvoren mi je jedan projekat u eclipse trenutno na kome radim, pa nebi da pravim jos jedan u workspacu ovome a mrzi me da menjam.. :d
Nadam se da sam ti barem malo pomogao u kom smeru da ides..
 
Poslednja izmena:
Hvala na pomoci, ali ja treba da unesem sa komandom <preuzmi ime fajla> , a server da ga potrazi i da ga vrati klijentu. Znaci na serveru postoje vise txt fajlova i u zavisnosti od toga koje sam ime uneo on salje dati fajl klijentu nazad ili javlja gresku da taj fajl ne postoji.
 
Pa treba prvo da modifikujes server i klijent, tako da oba imaju i input i output streamove.
Znaci klijent preko svog output streama pise ime fajla
Server preko svog input streama cita to ime i trazi ga u nekoj svojoj listi ili databazi ili sta vec.
Kad ga pronadje, server pise u svoj output stream text tog txt fajla
Klijent preko svog input streama cita text koji mu server salje.

Mrzi me da ti sad pisem kod, ali ako se bavis programiranjem pomuci se malo.
 
Hvala na pomoci, ali ja treba da unesem sa komandom <preuzmi ime fajla> , a server da ga potrazi i da ga vrati klijentu. Znaci na serveru postoje vise txt fajlova i u zavisnosti od toga koje sam ime uneo on salje dati fajl klijentu nazad ili javlja gresku da taj fajl ne postoji.

Dao sam ti link gore gde imas na slicnom primeru kako to da odradis. Znaci bukvalno imas sve delove slagalice a ja sam ti sa onim kodomm slozio kako da saljes fajl klientu, tebi je ostalo jos ostatak da odradis, jos ti je poljednostavljen zadatak s tim sto server radi samo sa jednim klientom...

A covek ispod ti je dao uputsva..

Evo ti neki pregled:

Server napravi socket
Client se konektuje

Sve dok ne primi STOP signal radi ovo:

Server ceka da primi sa DataInputStream-a zahtev za fajl
Kada primi napravi objekat klase ReadFromFile sa imenom fajla.
posalji taj fajl.

Ajd kad sam se vec raspisao.. -.-

Kod:
public class SimpleServer {
 
  public static void main(String args[]) throws IOException {
    // Register service on port 1234
    ServerSocket s = new ServerSocket(1234);
    Socket s1=s.accept(); // Wait and accept a connection
    
    // Get a communication stream associated with the socket
    OutputStream s1out = s1.getOutputStream();
    DataInputStream streamIn =  null; //input stream za server
    DataOutputStream dos = new DataOutputStream (s1out);
    Boolean stop = false;
    String line;
    while(!stop){
     try
            {  
              line = streamIn.readUTF();
              stop = line.equals(".stop"); //sve dok mu ne posaljes .stop server ce raditi..
            }
          catch(IOException ioe)
            {  stop = true;
            }
    if(!stop){     //ako si primio neki redi koji nije .stop signal onda idemo dalje, ako je stop preskaces ovaj blok izlazis iz while petlje i zavrsavas server
    ReadFromFile MyFile=new ReadFromFile("line"); 
    Scanner scn=MyFile.GetScanner();

     while(scn.hasNext())
         {

            String tmp=scanner.nextLine();
               // Send a string!
         dos.writeUTF(tmp);
        }
       dos.writeUTF(".eof"); //Da signaliziras klientu da je kraj fajla
     }
    }
    // Close the connection, but not the server socket
    dos.close();
    s1out.close();
    s1.close();
  }
}

Ovo mislim da ti je kompletan server kod. Klient ti je jos jednostavniji, sa ovim kodom bi trebao da ga napravis sa prostim copy-paste menjanem.. E da nisam testirao pisao sam iz glave, mada u teoriji to je to.. 😛
 
Poslednja izmena:
Posto se nisam do sada bavio java i socketima, a i imao sam par sati slobodnog vremena odradio sam ti program ceo za vezbu sebi i iztestirao ga. Bice ti potrebno paket usluge.Citaj od gospodina Lasla krausa( mrzelo me je da pisem citanje sa konzole iskreno) 😛
http://kondor.etf.rs/~kraus/knjige/programi/rzj2.zip
u zip fajlu imas Folder Usluge, samo ga prevuci u svoj projekat u eclipse..

E ovako evo ti kod,

Server:

Klasa ReadFromFile

Kod:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class ReadFromFile {
	File file;
	Scanner scanner;
	public ReadFromFile(String f)
	{
		file = new File (f);
		try {
			   System.out.println("Trying to read file: "+f);
	           scanner = new Scanner (file);
	        } catch (FileNotFoundException e) {
	          System.out.println ("File not found!");
	         System.exit (0);
	        }
	}
	public Scanner GetScanner(){return scanner;}

}


Klasa Sserver

Kod:
import java.net.*;
import java.io.*;

import java.util.Scanner;
public class Sserver {
	ServerSocket s;
	Socket s1;
	OutputStream s1out;
	DataInputStream streamIn;
	DataOutputStream dos;
	public Sserver(int port){
		try {
			System.out.println("Binding to port " + port + ", please wait  ...");
			s=new ServerSocket(port);
			System.out.println("Server started: " + s);
	         System.out.println("Waiting for a client ..."); 
	         s1 = s.accept();
	         System.out.println("Client accepted: " + s1);
	         dos = new DataOutputStream(s1.getOutputStream());
	         open();
	         Boolean stop= false;
	         String line=null;
	         while(!stop){
	        	 open();
	        	 try
	                    {  
	                      line = streamIn.readUTF();
	                      System.out.println("File name receved:"+ line);
	                      stop = line.equals(".stop"); //sve dok mu ne posaljes .stop server ce raditi..
	                    }
	                  catch(IOException ioe)
	                    {  
	                	  stop = true;
	                    close();
	                    }
	                  
	         if(!stop){
	       	 ReadFromFile MyFile=new ReadFromFile(line); 
	       	 Scanner scn=MyFile.GetScanner();
	        	 
	      	 while(scn.hasNext())
	    	 {
	      		 String temp=scn.nextLine();
	       		 dos.writeUTF(temp);
	        	 }
	        	 dos.writeUTF(".eof");
	         }
	         
	         }
	         } catch (IOException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
	
	public void open() throws IOException
	   {  streamIn = new DataInputStream(new BufferedInputStream(s1.getInputStream()));
	   }
	 public void close() throws IOException
	   {  if (s1 != null)    s1.close();
	      if (streamIn != null)  streamIn.close();
	     }
	}

Klasa main za server
Kod:
public class Main {

	public static void main(String[] args) {
System.out.println("Welcome to server");
Sserver server1= new Sserver(1225);//1225 port koji osluskuje
}
}


E sad klient:

Klasa Sclient:
Kod:
import java.net.*;
import java.io.*;
public class Sclient {

	Socket s1;
	InputStream s1In;
	OutputStream s1Ou;
    DataInputStream dis;
    DataOutputStream dos;
    
    public Sclient(String host, int port)
    {
    	System.out.println("Establishing connection. Please wait ...");
    	try{
        s1 = new Socket(host,port);
    	System.out.println("Connected to "+host+":"+port);
    	
         s1In = s1.getInputStream();
         s1Ou = s1.getOutputStream();
    	 dis = new DataInputStream(s1In);
    	 dos = new DataOutputStream(s1Ou);
    	}catch(UnknownHostException uhe)
        {  System.out.println("Host unknown: " + uhe.getMessage());}
        catch(IOException ioe)
        {System.out.println("Unexpected exception: " + ioe.getMessage());}
    }
	
    public void SendReq(String fname)//Funkcija koja salje ime fajla serveru
    {
    	try {
			dos.writeUTF(fname);
		} catch (IOException e) {
			System.out.println("Error sending request: "+ e.getMessage());
			e.printStackTrace();
		}
    }
    public void ReadFile(){ //Funckija koja prima fajl od servera
    	try {
			Boolean eof = false;
			while(!eof){  //Gledamo dal smo stigli do kraja fajla
			String line=dis.readUTF();
            eof = line.equals(".eof");
            if(!eof){System.out.println(line);} //Ako nismo primili .eof za kraj odstampaj linuju
            else {System.out.println("End of file");}

			}
		} catch (IOException e) {
			System.out.println("Error receving file: "+ e.getMessage());
			e.printStackTrace();
		}
    }
}

i klasa main za klient:
Kod:
import usluge.Citaj;
public class Main {

	public static void main(String[] args) {
		
		System.out.println("Welcome, enter server address, and port");
		String server= Citaj.String();//citamo server i port
		int port =Citaj.Int();        // sa glavnog ulaza
		Sclient client = new Sclient(server,port); //pravimo objekat klase Sclient
		while(true){     //Vrtimo se sve dok ne izdamo narednu .exit
		System.out.println("Enter file name or path on server or .exit to exit");
		String file=Citaj.String();
		if(file.equals(".exit"))System.exit(1);
		client.SendReq(file);//saljemo request za file
		client.ReadFile();  // Primamo file i ispisujemo
		}
	}

}

Evo nadam se da je sve jasno.. Koristio sam engleski za poruke, posto tako volim ***.. 😛
 
Poslednja izmena:
^Imam pitanje za nnnn lice 🙂
Dobro su napisane klase, ali mi nije jasno čemu služi taj paket usluge.Citaj koji je trebalo downloadovati iz onog zipovanog fajla? Koliko sam shvatio autoru ovog topica treba program gde će klijent putem tastature da unese ime fajla i onda ga dobije od servera, a ja koliko znam to može da se uradi preko BufferedReader-a (br = new BufferedReader(new InputStreamReader(system.in))), ali nigde ne vidim tu liniju koda.. jel za to u stvari služi taj paket?

I drugo pitanje, ako može objašnjenje,
u čemu je razlika između
DataInputStream
i
InputStream
( i po analogiji, DataOutputStream - OutputStream) to me zbunjuje!!
Jel smo mogli da npr. ove dve linije koda
Kod:
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream (s1out);
zamenimo jednom
Kod:
DataOutputStream dos = new DataOutputStream(s1.getOutputStream())
kako ne bismo mešali OutputStream i DataOutputStream?
 
Pa ja mogu da ti odgovorim na drugo pitanje.

Da te dve linije koda su mogle da se zamene sa ovom koju si predlozio, i ne bi bilo nikakve razlike u funkcionisanju ovog programa.

A sto se tice razlike DataInputStreama i InputStreama, ove klase predstavljaju dobar primer decorator pattern-a. Klasa InputStream implementira neke osnovne mogucnosti kao sto je citanje niza bajtova iz toka (streama), a klasa DataInputStream "dekorisanjem" osnovne klase InputStream (koja joj je prosledjena u konstruktoru) dodaje neke nove metode, kao sto je metoda readUTF koju je nnn koristio.
 
^Imam pitanje za nnnn lice 🙂
Dobro su napisane klase, ali mi nije jasno čemu služi taj paket usluge.Citaj koji je trebalo downloadovati iz onog zipovanog fajla? Koliko sam shvatio autoru ovog topica treba program gde će klijent putem tastature da unese ime fajla i onda ga dobije od servera, a ja koliko znam to može da se uradi preko BufferedReader-a (br = new BufferedReader(new InputStreamReader(system.in))), ali nigde ne vidim tu liniju koda.. jel za to u stvari služi taj paket?

I drugo pitanje, ako može objašnjenje,
u čemu je razlika između
DataInputStream
i
InputStream
( i po analogiji, DataOutputStream - OutputStream) to me zbunjuje!!
Jel smo mogli da npr. ove dve linije koda
Kod:
OutputStream s1out = s1.getOutputStream();
DataOutputStream dos = new DataOutputStream (s1out);
zamenimo jednom
Kod:
DataOutputStream dos = new DataOutputStream(s1.getOutputStream())
kako ne bismo mešali OutputStream i DataOutputStream?


Paket usluge, klasa citaj, je skup funkcija za citanje raznih vrsta promenjivih sa standardnog ulaza( tacnije tastature 😛).. Ja sam uvek koristio to, posto je provereno i testirano. ( A i iskreno da kazem, navika :smash: )

A pod dva, vec je odgovorio kolega iznad 😛
 
Poslednja izmena:
Jao, jel može neko da mi pomogne oko sledećeg koda, je6em se sa ovim već satima, ne znam u čemu je problem:

Imam Client klasu i Server klasu. Server radi,testirao sam sa nekim jednostavnijim primerom. Sve sto server treba da uradi je da Syso jednu običnu rečenicu koju primi od strane klijenta.
Uspem da povežem klijenta i server, i hteo sam da kada klijent upise neki tekst u jedno polje i pritisne dugme, taj tekst se posalje serveru i da ga on ispise, čisto da vidim da ga je primio. Međutim ništa se ne dešava. Nema ni exception-a.

Evo koda, stavio sam najvažniji deo, GUI nije bitan..

ClientGUI:
Kod:
public class Client GUI{

             public DataInputStream DIS;
	public DataOutputStream DOS;
	public Socket clientSocket;
	

public void KonektujSe(){
		String Adresa = getAdresaServera().getText();
		
		try {
			
			 clientSocket = new Socket(Adresa,1234);
			 DOS = new DataOutputStream(clientSocket.getOutputStream());
			 DIS = new DataInputStream(clientSocket.getInputStream());
			
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
		System.out.println("Neispravna adresa servera");
		} catch (IOException e) {
		System.out.println("Neispravan unos");
		}
		
	}
	
	

public void Posalji(String tekst) throws Exception{
		 
		DOS.writeUTF(tekst);
	}



private JButton getPOSALJI() {
		if (POSALJI == null) {
			POSALJI = new JButton();
			POSALJI.setBounds(new Rectangle(351, 197, 136, 28));
			POSALJI.setText("POSALJI");
			POSALJI.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {

				try {
					Posalji(getTekstOdgovora().getText()); // getTekstOdgovora je polje gde se upisuje rečenica
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
					
				}
			});
		}
		return POSALJI;
	}



public static void main(String[] args) {	
		
	 
	 
		SwingUtilities.invokeLater(new Runnable() {
			
			public void run() {
				ClientGUI application = new ClientGUI();
				application.getJFrame().setVisible(true);
					}
		});
	}

U čemu je problem?
 
U metodi Posalji posle linije DOS.writeUTF(tekst) dodaj liniju:
DOS.flush();
 
Hvala na dobroj volji , međutim nije to bio problem već to što kod dugmeta getPosalji nisam u okviru linije koda
Kod:
Posalji(getTekstOdgovora().getText());
dodao "\n" pa da bude :wall:
Kod:
Posalji(getTekstOdgovora().getText() + "\n");
jer kod servera koristim metodu ReadLine() za čitanje toga što mu pošalje klijent..
Ali šta ću, prvi put se susrećem sa tim metodama,ne znam kako koja funkcioniše..

Pokušao sam samo da dodam tu liniju DOS.flush() pa da vidim šta će biti, međutim onda mi se ispiše samo neki kvadrat ?! A ovako kad ubacim "\n" prvo ide par kvadrata pa onda pravi tekst. Šta predstavljaju ti kvadrati?

I imam još jedno pitanje,
kada hoću da npr.
pošaljem serveru neki String
server izmeni taj string (npr. sve u mala slova)
pa ga vrati nazad klijentu
, da bi klijent to primio, jel dovoljno da samo ispod linije
Kod:
Posalji(getTekstOdgovora().getText() + "\n\);
dodam liniju
Kod:
DIS.readLine()
// Data input stream?
Tj. jel nije potrebno da kod klijenta pravim niti i imam petlje while(true) za primanje od servera (ako računamo da će server slati klijentu samo u trenutku kada mu klijent nešto zatraži, tj. pošalje nešto)?

EDIT evo uspeo sam da zaobidjem čudne kvadrate, korišćenjem metode writeBytes umesto writeUTF!
I drugo, pokušao sam da uradim to što sam pitao i radi, ali kada dodam neki drugi tekst u prozor i opet pritisnem dugme da pošalje, onda zablokira! Šta bi trebalo da uradim kako bih to mogao da popravim?
 
Poslednja izmena:
Probaj ovako:
public DataOutputStream DOS; zameni sa
private PrintWriter DOS;

dole u metodi KonektujeSe zameni
DOS = new DataOutputStream(clientSocket.getOutputStream());
sa
DOS = new PrintWriter(clientSocket.getOutputStream());

i u metodi Posalji stavi samo ove dve linije:
DOS.write(tekst + System.getProperty("line.separator"));
DOS.flush();

Dakle na svim mestima gde imaš neku metodu gde čitaš liniju po liniju, bolje umesto \n koristi System.getProperty("line.separator") kako bi imao kompatibilnost programa na svim sistemima za koje postoji virtuelna mašina...
 
Poslednja izmena:
Nazad
Vrh Dno