Përshëndetje.
Sot, sot, do t'ashĂ«rojmĂ« procesin e krijimit tĂ« aplikacioneve klient-server qĂ« kryejnĂ« funksionet e utilitarĂ«ve standard tĂ« Windows, si Telnet, TFTP, e tĂ« tjera, nĂ« Java tĂ« pastĂ«r. E kuptoj qĂ« nuk po sjell asgjĂ« tĂ« re â tĂ« gjithĂ« kĂ«ta utilitarĂ« kanĂ« funksionuar me sukses pĂ«r njĂ« kohĂ« tĂ« gjatĂ«, por mendoj se nuk tĂ« gjithĂ« e dinĂ« çfarĂ« ndodh nĂ«n kapakĂ«t e tyre.
Pikërisht rreth kësaj do të flasim më poshtë.
NĂ« kĂ«tĂ« artikull, qĂ« tĂ« mos e zgjat, pĂ«rveç informacionit tĂ« pĂ«rgjithshĂ«m do tĂ« shkruaj vetĂ«m pĂ«r serverin Telnet, por deri tani ka materiale edhe pĂ«r utilitarĂ« tĂ« tjerĂ« â ato do tĂ« jenĂ« nĂ« pjesĂ«t e ardhshme tĂ« ciklit.
SĂ« pari, duhet tĂ« kuptojmĂ« se çfarĂ« Ă«shtĂ« Telnet, pĂ«r çfarĂ« shĂ«rben dhe si pĂ«rdoret. Nuk do tĂ« citoj burimet fjalĂ« pĂ«r fjalĂ« (nĂ«se Ă«shtĂ« e nevojshme â nĂ« fund tĂ« artikullit do ngjisim njĂ« lidhje me materialet pĂ«r temĂ«n), do tĂ« them vetĂ«m se Telnet siguron akses tĂ« largĂ«t nĂ« komandĂ«n e pajisjes. NĂ« thelb, kĂ«tu pĂ«rfundon funksionaliteti i tij (pĂ«r adresimin e portit tĂ« serverit nuk po flasim tani, pĂ«r kĂ«tĂ« do tĂ« theksoj mĂ« vonĂ«). KĂ«shtu, pĂ«r ta realizuar atĂ«, na nevojitet tĂ« pranojmĂ« njĂ« varg nĂ« klient, ta transferojmĂ« nĂ« server, tĂ« pĂ«rpiqemi ta dĂ«rgojmĂ« nĂ« komandĂ«n e terminalit, tĂ« lexojmĂ« pĂ«rgjigjen e komandĂ«s, nĂ«se ka, ta dĂ«rgojmĂ« atĂ« pĂ«rsĂ«ri nĂ« klient dhe tĂ« shfaqim nĂ« ekran, ose nĂ« rast tĂ« njĂ« gabimi, t'i bĂ«jmĂ« tĂ« ditur pĂ«rdoruesit se diçka nuk Ă«shtĂ« nĂ« rregull.
Për realizimin e asaj që përmenda më sipër, na duhen përkatësisht 2 klasa funksionale dhe një klasë testuese, nga e cila do të nisnim serverin dhe përmes së cilës do të funksiononte klienti.
Struktura e aplikacionit aktualisht përfshin:
- TelnetClient
- TelnetClientTester
- TelnetServer
- TelnetServerTester
Le të shohim secilën prej tyre:
TelnetClient
Gjithçka që duhet të bëjë kjo klasë është të dërgojë komandat që merr dhe të tregojë përgjigjet që merr. Për më tepër, duhet të jetë në gjendje të lidhet me një port të caktuar (për të cilin flas më lart) të pajisjes së largët dhe të shkëputet nga ai.
Për këtë janë realizuar funksionet e mëposhtme:
Një funksion që merr si argument adresën e socket-it, hap lidhjen dhe nis rrjedhat e hyrjes dhe daljes (variablat e rrjedhave janë shpallur më sipër, burimet e plota do të jenë në fund të artikullit).
public void run(String ip, int port)
{
try {
Socket socket = new Socket(ip, port);
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
Scanner keyboard = new Scanner(System.in);
reader = new Thread(()->read(keyboard, sout));
writer = new Thread(()->write(sin));
reader.start();
writer.start();
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
Nuk ndryshojmĂ« kĂ«tĂ« funksion, i cili lidhet me portin e parazgjedhur â pĂ«r telnetin, ky Ă«shtĂ« 23.
public void run(String ip)
{
run(ip, 23);
}
Funksioni lexon karakteret nga tastiera dhe i dĂ«rgon ato nĂ« socket-in e daljes â çfarĂ« Ă«shtĂ« karakteristik, nĂ« modin e vargut, e jo atĂ« tĂ« karaktereve:
private void read(Scanner keyboard, OutputStream sout)
{
try {
String input = new String();
while (true) {
input = keyboard.nextLine();
for (char i : (input + " n").toCharArray())
sout.write(i);
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
Funksioni merr të dhëna nga socket-i dhe i shfaq ato në ekran.
private void write(InputStream sin)
{
try {
int tmp;
while (true){
tmp = sin.read();
System.out.print((char)tmp);
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
Funksioni ndalon pranimin dhe dërgimin e të dhënave.
public void stop()
{
reader.stop();
writer.stop();
}
}TelnetServer
Kjo klasĂ« duhet tĂ« ketĂ« funksionalitetin pĂ«r tĂ« pranuar komanda nga socket-i, pĂ«r t'i dĂ«rguar ato pĂ«r ekzekutim dhe pĂ«r tĂ« dĂ«rguar pĂ«rgjigjen e komandĂ«s mbrapsht nĂ« socket. NĂ« program nuk ka kontroll pĂ«r tĂ« dhĂ«nat e hyrshme, sepse sĂ« pari, edhe nĂ« âtelnet-in e kutisĂ«â ka mundĂ«sinĂ« tĂ« formatosh diskun e serverit, dhe sĂ« dyti, çështja e sigurisĂ« nĂ« kĂ«tĂ« artikull Ă«shtĂ« e anashkaluar dhe pĂ«r kĂ«tĂ« arsye kĂ«tu nuk ka asnjĂ« fjalĂ« pĂ«r enkriptimin ose SSL.
Këtu ka vetëm 2 funksione (njëra prej tyre është e overload-uar), dhe në përgjithësi kjo nuk është një praktikë shumë e mirë, megjithatë, në kuadër të kësaj detyre, më duket e arsyeshme ta lë të gjitha siç janë.
boolean isRunning = true;
public void run(int port) {
(new Thread(()->{ try {
ServerSocket ss = new ServerSocket(port); // krijojmë soketin e serverit dhe e lidhi atë me portin e mësipërm
System.out.println("Port " + port + " është duke pritur për lidhje");
Socket socket = ss.accept();
System.out.println("I lidhur");
System.out.println();
// Marrim rrjedhat hyrëse dhe dalëse të soketit, tani mund të marrim dhe dërgojmë të dhëna klientit.
InputStream sin = socket.getInputStream();
OutputStream sout = socket.getOutputStream();
Map<String, String> env = System.getenv();
String wayToTemp = env.get("TEMP") + "tmp.txt";
for (int i : ("I lidhurnnr".toCharArray()))
sout.write(i);
sout.flush();
String buffer = new String();
while (isRunning) {
int intReader = 0;
while ((char) intReader != 'n') {
intReader = sin.read();
buffer += (char) intReader;
}
final String inputToSubThread = "cmd /c " + buffer.substring(0, buffer.length()-2) + " 2>&1";
new Thread(()-> {
try {
Process p = Runtime.getRuntime().exec(inputToSubThread);
InputStream out = p.getInputStream();
Scanner fromProcess = new Scanner(out);
try {
while (fromProcess.hasNextLine()) {
String temp = fromProcess.nextLine();
System.out.println(temp);
for (char i : temp.toCharArray())
sout.write(i);
sout.write('n');
sout.write('r');
}
}
catch (Exception e) {
String output = "Dicka shkoi keq... Kodi i gabimit: " + e.getStackTrace();
System.out.println(output);
for (char i : output.toCharArray())
sout.write(i);
sout.write('n');
sout.write('r');
}
p.getErrorStream().close();
p.getOutputStream().close();
p.getInputStream().close();
sout.flush();
}
catch (Exception e) {
System.out.println("Gabim: " + e.getMessage());
}
}).start();
System.out.println(buffer);
buffer = "";
}
}
catch(Exception x) {
System.out.println(x.getMessage());
}})).start();
}
Programi hap një port serveri, lexon të dhënat nga ai derisa të takojë simbolin e përfundimit të komandës, e dërgon komandën në një proces të ri, dhe rezultati nga ai proces drejtohet në soket. E thjeshtë si një automat Kalashnikov.
Në përputhje me këtë, ekziston një mbingarkesë për këtë funksion me portin sipas parazgjedhjes:
public void run()
{
run(23);
}Po ashtu, funksioni qĂ« ndalon serverin â gjithashtu Ă«shtĂ« i thjeshtĂ«, ai ndĂ«rpret ciklin e pĂ«rjetshĂ«m, duke shkelur kushtin e tij.
public void stop()
{
System.out.println("Serveri u ndal");
this.isRunning = false;
}Nuk do tĂ« jap kĂ«tu klasat testuese, ato janĂ« mĂ« poshtĂ« â gjithçka qĂ« ato bĂ«jnĂ« Ă«shtĂ« tĂ« verifikojnĂ« funksionalitetin e metodave publike. TĂ« gjitha janĂ« nĂ« git.
Pra, pĂ«r tĂ« pĂ«rmbledhur, pĂ«r disa mbrĂ«mje mund tĂ« kuptoni parimet e funksionimit tĂ« utilitarĂ«ve tĂ« zakonshĂ«m tĂ« konsolĂ«s. Tani, kur ne lidhim me kompjuterin e largĂ«t, ne kuptojmĂ« se çfarĂ« po ndodh â magia ka, pra, humbur)
Pra, lidhjet:
Burimi: habr.com
