Network
Modern Programming Languages
12
เน็ตเวิรค (Network) 12.1 • • •
12.2 • •
เน็ตเวิรค (Network) เครือขายของคอมพิวเตอรหลายเครื่องสามารถรับสงขอมูลระหวางกัน โดยอาศัยกฎเกณฑหรือขอตกลง เดียวกัน (protocol) ในภาษาจาวาสนับสนุนการเชื่อมตอเครือขาย ดวย Socket ซึ่งจะทําการสรางชองทางเพื่อทําการสง ขอมูลผานระบบเครือขาย ในภาษาจาวาสนับสนุนการติดตอแบบ stream socket และ datagram socket Stream socket
การติดตอโดยใชโปรโตคอล TCP ที่รับรองการทํางานแบบ connection-oriented คือการรับสงขอมูลจะ เริ่มตน ตองมีการเชื่อมตอระหวางผูรับและผูสงกอน หากขอมูลสงไปไมถึงปลายทางหรือสูญหาย จะมีการรองขอขอมูลเหลานั้นอีก ซึ่งสามารถรับประกันการ สูญหายได Server
Client
Create Socket
Create Socket Client รองขอการเชื่อมตอไปที่ Server
Accept
Connect
ทําการเชื่อมตอกันระหวาง Server/Client Read/Write
12.3 • •
ทําการรับสงขอมูล
Read/Write
Datagram socket
การติดตอโดยใชโปรโตคอล UDP ที่รองรับการทํางานแบบ connection-less คือในการรับสงขอมูลไม จําเปนตองมีการเชื่อมตอ socket ระหวางผูรับกับผูสงเขาดวยกัน การรับสงขอมูลแบบ UDP ขอมูลอาจสูญหาย และไมรับประกันความถูกตองวาจะสงถึงปลายทาง Server
Client
Create Socket
Create Socket
ทําการรับสงขอมูล Read/Write
[email protected]
Read/Write
1/21
Network
12.4
Modern Programming Languages
คลาสแพ็คเกจ java.net •
InetAddress สําหรับเก็บ IP Address
•
Socket สรางการติดตอโดยใชโปรโตคอล TCP
•
Serversocket สราง server โดยใชโปรโตคอล TCP
•
DatagramPacket เก็บขอมูลในการสงและรับ โดยใชโปรโตคอล UDP
•
DatagramSocket ใชในสงและรับขอมูลโดยใชโปรโตคอล UDP
คลาส InetAddress • ใชเก็บ IP Address ซึ่งใชไดกับทั้งโปรโตคอล TCP และ UDP • การเก็บขอมูลเกี่ยวกับ IP Address อาจจะมี domain name ของ IP Address • ไมมี constructor แตมี static method สําหรับสรางออบเจกตของคลาส InetAddress คือ o •
public static InetAddress getLocalHost() throws UnknownHostException ทําใหสรางออบเจกตของคลาส InetAddress และสามารถเรียกใชงานเมธอดดังนี้
เมธอดตางๆของคลาส InetAddress ที่สําคัญมีดังนี้ o o o o o
o
public String getHostName() เรียกขอ domain name public String getHostAddress() เรียกขอ IP Address public byte[] getAddress() เรียกขอ IP Address ในรูปของ byte public static InetAddress getByName(String s) throws UnknownHostException ทําการเปลี่ยน domain name ไปเปน IP Address public static InetAddress getAllByName(String[] s) throws UnknownHostException บาง domain name อาจจะมีหลาย IP Address public static InetAddress getByAddress(byte[] b) throws UnknownHostException ทําการเปลี่ยน IP Address ไปเปน domain name
ตัวอยาง การใชเมธอด getLocalHost()
• •
หากทําการรันโปรแกรมบนเครื่องที่มี DNS ใหบริการอยูจะได InetAddress ของเครื่องนั้น หากไมตอกับระบบเครือขายก็จะไดตามคาที่ตั้งไวในระบบปฏิบัติการ
[email protected]
2/21
Network
Modern Programming Languages
ผลลัพธที่ได เมื่อไมไดติดตอผานเครือขาย จะไดดังรูปดานลาง
เมื่อติดตอผานเครือขาย จะไดดังรูปดานลาง
ตัวอยาง การใชเมธอด getAddress()
ผลลัพธที่ได 203.148.150.118
ตัวอยาง การใชเมธอด getByName()
ผลลัพธที่ได 203.148.159.2
[email protected]
3/21
Network
Modern Programming Languages
ตัวอยาง การใชการใชเมธอด getAllByName()
ผลลัพธที่ได
ตัวอยาง การใชเมธอด getByAddress()
ผลลัพธที่ได
[email protected]
4/21
Network
Modern Programming Languages
คลาส Socket • สรางการติดตอไปยังเปาหมาย ที่พอรตหนึ่ง โดยเครื่องเปาหมายอาจเปนผูรับหรือผูสงก็ได • ทําการสราง stream สําหรับอานหรือเขียนขอมูลไปที่เครื่องเปาหมาย • คลาส Socket มี constructor ที่สําคัญดังนี้ o
public Socket(String host,int port) throws UnknownHostException, IOException ทําการสราง socket เพื่อทําการติดตอ host ที่ตําแหนง port
คลาส ServerSocket • สรางการติดตอระหวางเครื่องสองเครื่องผานทาง Socket • เครื่องที่รอรับการติดตอ เรียกวา server • เครื่องที่เปนผูติดตอ เรียกวา client • คลาส ServerSocket มี constructor ที่สําคัญดังนี้ o
public ServerSocket(int port) throws IOException ทําการสราง server socket เพื่อทําการติดตอที่ตําแหนง port
เชน ServerSocket ss = new ServerSocket(8000); เมื่อสรางออบเจกตของ ServerSocket จะตองรอรับการเชื่อมตอจาก client ดวยการเรียกใชเมธอด accept() โดยเมื่อมีการเชื่อมตอ จะทําการสราง socket สําหรับให server รับสงขอมูลกับ client
ดังนี้ Socket s = ss.accept();
ตัวอยาง การใชการใชเมธอด TCP Client/Server แบบคราวๆ ss “Hello” out “Hi” in s
Socket connection port established 8000
//ทําการติดตอ server Socket s = new Socket( “localhost”, 8000 ); // สราง streams เพื่ออานขอมูลจาก server BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() )); // สราง streams เพื่อเขียนขอมูลไปยัง server PrintStream out = new PrintStream( s.getOutputStream() ); // อานเขียนขอมูลไปยัง server out.println( “Hello” ); out.flush(); String t = in.readLine(); System.out.println( t ); in.close(); out.close(); s.close();
[email protected]
localhost in “Hello” out “Hi” s
// สราง ServerSocket ติดตอที่ port 8000 ServerSocket ss = new ServerSocket( 8000 ); // รอรับการติดตอจาก client Socket s = ss.accept(); // สราง streams เพื่ออานขอมูลจาก client BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() )); // สราง streams เพื่อเขียนขอมูลไปยัง server PrintStream out = new PrintStream( s.getOutputStream() ); // อานเขียนขอมูลไปยัง client String t = in.readLine(); System.out.println( t ); out.println( “Hi” ); out.flush(); in.close(); out.close(); s.close(); ss.close();
5/21
Network
Modern Programming Languages
ตัวอยาง การสงเมล
ทําการพิจารณาการทํางาน ในแตละคําสั่งดังนี้ • ทําการติดตอโดยใช telnet ที่พอรต 25 o •
o •
Socket s = new Socket(“mail.mut.ac.th”,25);
เมื่อทําการติดตอได server จะสงขอมูลตอบกลับ สังเกตไดคือ จะมีตัวเลข 3 หลักขึ้นตนบรรทัด และ ตามดวยขอความ 220 relay.mut.ac.th ESMTP Sendmail 8.12.11/8.12.11; Tue, 6 Sep 2005 21:08:35 +0700
โดยเราสงการทักทายกลับดวย o
ps.println("HELO mail.mut.ac.th");
[email protected]
6/21
Network
Modern Programming Languages
•
server จะสงขอมูลตอบกลับ o 250 relay.mut.ac.th Hello digital-214.modem.mut.ac.th [203.209.48.214], pleased to meet you
•
เราสงคําสั่ง วาสงเมลโดยจากใคร o
ps.println("MAIL FROM:
[email protected]"); โดยรูปแบบคําสั่งที่สงไปคือ MAIL FROM: Email Address
•
server จะสงขอมูลตอบกลับ o 250 2.1.0
[email protected] ... Sender ok
•
เราสงคําสั่ง วาสงเมลไปที่หาใคร o o
• • • • •
• • •
String Addressee= "
[email protected]"; ps.println("RCPT TO: " + Addressee ); โดยรูปแบบคําสั่งที่สงไปคือ RCPT TO: Email Address
server จะสงขอมูลตอบกลับ o 250 2.1.5
[email protected] ... Recipient ok เราสงคําสั่ง วาจะทําการเขียน message o ps.println("DATA");
เราสงคําสั่ง ในการสงหัวขอเมล o ps.println("SUBJECT: " + "Test Send Mail" ); server จะสงขอมูลตอบกลับ message o 354 Please start mail input เราสง Message และทําการสง message จบดวย “.”ดังนี้ o ps.println("This is the message\n that Java sent"); o ps.println("Hello, How are you?"); o ps.println("."); server จะสงขอมูลตอบกลับวาขอมูลทําการสงแลว o 250 Mail queued accepted for delivery. สงคําสั่งสิ้นสุดการติดตอกับ server o ps.println("QUIT"); server จะสงขอมูลตอบกลับ o 221 Closing connection. Good bye.
ผลลัพธที่ได
[email protected]
7/21
Network
Modern Programming Languages
ตัวอยาง การสราง TCP Server import java.io.*; import java.net.*; public class SimpleServer { public static void main( String args[] ) { try { ServerSocket ss = new ServerSocket( 8000 ); System.out.println( "Server : Waiting for connection ..." ); Socket s = ss.accept(); BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() ) ); PrintStream out = new PrintStream( s.getOutputStream() ); String t = in.readLine(); System.out.println( t ); out.println( "Hi" ); out.flush(); try { Thread.sleep( 1000 ); } catch ( Exception e ) { } in.close(); out.close(); s.close(); ss.close(); }catch ( Exception e ) { System.out.println( "Error: " + e ); } } //End main } // End class SimpleServer
ตัวอยาง การสราง TCP Client import java.io.*; import java.net.*; public class SimpleClient { public static void main( String args[] ) { try { Socket s = new Socket( "localhost", 8000 ); BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() ) ); PrintStream out = new PrintStream( s.getOutputStream() ); out.flush(); out.println( "Hello" ); String t = in.readLine(); System.out.println( t ); try { Thread.sleep( 1000 ); } catch ( Exception e ) { } in.close(); out.close(); s.close(); } catch ( Exception e ) { System.out.println( "Error" + e ); } } }
[email protected]
8/21
Network
Modern Programming Languages
ผลลัพธที่ได o เมื่อรันโปรแกรม SimpleServer Server รอรับการเชื่อมตอจาก Client o
เมื่อรันโปรแกรม SimpleClient Client ทําการรองขอการติดตอไปยัง Server หากการเชื่อมตอสําเร็จ • Server สงขอความ “Hi” ไปยัง Client ฝง Client แสดงดังรูป •
Client สงขอความ “Hello” ไปยัง ฝง Server แสดงดังรูป
คลาส DatagramPacket • ใชสําหรับเก็บขอมูล byte[] เปน packet เรียกวา datagram • คลาส DatagramPacket มี constructor ที่สําคัญดังนี้ o
public DatagramPacket(byte[] b,int length)
เพื่อเก็บขอมูลที่เขามา o •
public DatagramPacket(byte[] b,int length, InetAddress address,int port)
เพื่อเก็บขอมูลที่จะสงออกไป มีเมธอดที่สําคัญ ดังนี้
o public byte[] getData() o public int getLength() o public int getPort() คลาส DatagramSocket • •
ใชในการสงและรับขอมูล datagram คลาส DatagramSocket มี constructor ที่สําคัญดังนี้ o o
•
public DatagramSocket (in port) throws SocketException รับขอมูล datagram ที่เขามา public DatagramSocket () throws SocketException สงขอมูล datagram ออกไป
มีเมธอดที่สําคัญใชในการรับสงขอมูล ดังนี้ o o
public void send(DatagramPacket p) throws IOException public void receive(DatagramPacket p) throws IOException
ตัวอยาง การใชการใชเมธอด UDP Client/Server Client
Server ds.send(outDataPacket)
ds.send(outDataPacket) ds.receive(inDataPacket) ds DatagramSocket ds; ds = DatagramSocket();
[email protected]
port 8000
ds.receive(inDataPacket) ds DatagramSocket ds; ds = DatagramSocket(8000);
9/21
Network
Modern Programming Languages
ตัวอยาง การสราง UDP Server import java.io.*; import java.net.*; import java.util.*; public class UDPServer { //This method retrieves the current time on the server public byte[] getTime() { Date d = new Date(); return d.toString().getBytes(); } //main server loop public void go () throws IOException { DatagramSocket datagramSocket; DatagramPacket inDataPacket; //from client DatagramPacket outDataPacket; // to client InetAddress clientAddress; //client return address int clientPort; //client return port byte [] msg = new byte[100]; // data in buffer byte[] time; //store retrieved time //Allocate a socket to port datagramSocket = new DatagramSocket(8000); System.out.println("UDP Server active on port 8000"); while(true) { //loop forever //set up recieve packet. data will be ignored. inDataPacket = new DatagramPacket(msg, msg.length); datagramSocket.receive(inDataPacket); //get message //retrieve return address information, including InetAddress //and port from the datagram packet just recieved clientAddress = inDataPacket.getAddress(); clientPort = inDataPacket.getPort(); time = getTime();//get the current time String recvMsg = new String(inDataPacket.getData()).trim(); //String recvMsg = new String(inDataPacket.getData(), //0,inDataPacket.getLength()); //if (recvMsg.equals("QUIT")) //break; System.out.println(recvMsg); //send datagram to be sent to the client using //current time, the client address and port outDataPacket = new DatagramPacket(time,time.length, clientAddress,clientPort); datagramSocket.send(outDataPacket); //finally send the packet } } public static void main(String [] args) { UDPServer udpServer = new UDPServer(); try { udpServer.go(); } catch (IOException e) { System.out.println("IOException occured with socket."); System.out.println(e); System.exit(1); } } }
[email protected]
10/21
Network
Modern Programming Languages
ตัวอยาง การสราง UDP Client import java.io.*; import java.net.*; import java.util.*; public class UDPClient { //main server loop public void go () throws UnknownHostException,IOException { DatagramSocket datagramSocket; DatagramPacket inDataPacket; //from server DatagramPacket outDataPacket; // to server InetAddress serverAddress; //server host address String receiveMsg; //Receive message in string form byte [] msg = new byte[100]; // buffer space msg = "Hello, How are you?".getBytes(); //Allocate a socket by which message are sent and received. datagramSocket = new DatagramSocket(); //server is running on this same machine for this example //this method can throw an UnknowHostException //serverAddress = InetAddress.getLocalHost(); //set up a datagram request to be sent to the server. //send to port 8000 //outDataPacket = new DatagramPacket(msg, 1, serverAddress, 8000); outDataPacket = new DatagramPacket(msg, msg.length,"localhost", 8000); //make request to thhe sever. datagramSocket.send(outDataPacket); inDataPacket = new DatagramPacket(msg, msg.length); // receive the time data the server datagramSocket.receive(inDataPacket); //print the data received from the server receiveMsg = new String(inDataPacket.getData(), 0,inDataPacket.getLength()); System.out.println(receiveMsg); //close the socket datagramSocket.close(); } public static void main(String [] args) { UDPClient udpClient = new UDPClient(); try { udpClient.go(); } catch (IOException e) { System.out.println("IOException occured with socket."); System.out.println(e); System.exit(1); } } }
[email protected]
11/21
Network
12.5 •
Modern Programming Languages
Multiple Connection
ใช Thread มีการทํางานดังนี้ o Main Thread สรางลูปไมรูจบ รอรับการติดตอจาก client
o
while ( true ) { Socket s = ss.accept(); CThread ct = new CThread( s ); ct.start(); } Connection Thread สราง thread ในการติดตอกับ 1 client ทําการรับสงขอมูล public void run() { // get input streams // read/write client // loop } localhost
ss connection thread public void run() { // get input streams // read/write client // loop }
port 8000 connection thread s
while ( true ) { Socket s = ss.accept(); main CThread ct = new CThread( s ); thread ct.start(); } connection thread Notes:
•
s
s
•
s
create and start 1 new thread client
client
client
main thread just accepts
s
s
[email protected]
12/21
Network
Modern Programming Languages
ตัวอยาง การสราง MultiConnection import java.util.*; import java.io.*; import java.net.*; public class MultiConnect { public static void main( String args[] ) { Vector myConnections = new Vector(); try { ServerSocket ss = new ServerSocket( 8888 ); // loop accepting new connections while ( true ) { System.out.println( "Waiting for connection ..." ); // wait for another client to connect // (note: each time through the loop, s gets a _different_ socket // even though it's the same name) // s is just a temporary variable good for just an iteration // to save the socket, we create a new thread // and give it the socket Socket s = ss.accept(); System.out.println( "Connection established with " + s.getInetAddress() ); SConnectionThread t = new SConnectionThread( s ); // note: addElement is not synchronized // but in this case, it's not a problem. // Race conditions are only a problem if there is more // one thread trying to use an object at the same time. // In this case, even though there are multiple clients, // there is only 1 thread using myConnections -- the main thread. // Therefore, we don't need to synchronize. // If other threads use myConnections, then we would // need to either: // 1) create a new class that "wraps" a Vector // and has synchronized methods that simply forward to the // Vector // or 2) use a synchronized block synchronized on myConnections myConnections.addElement( t ); t.start(); } } catch ( Exception e ) { System.out.println( "Error in main thread: " + e ); } } //End main } //End class MultiConnection
[email protected]
13/21
Network
Modern Programming Languages
ตัวอยาง การสราง SConnectionThread class SConnectionThread extends Thread { protected Socket s; public SConnectionThread( Socket s ) { this.s = s; } //End Constructor public void run(){ try { // get streams to allow us to read // and write to client BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() )); PrintStream out = new PrintStream( s.getOutputStream() ); // loop until client closes or the connection gets cut // (in which case, inTxt will be null // or we get an exception) String inTxt = null; do { // read from client inTxt = in.readLine(); if ( inTxt != null ) { System.out.println( "Received from client " + s.getInetAddress() + ": " + inTxt ); // write to client String outTxt = "s" + inTxt; System.out.println( "Sending to client " + s.getInetAddress() + ": " + outTxt ); out.println( outTxt ); out.flush(); // Note: In this case, we choose not to put a delay here. // Server gets ready to receive more from client right away. // (It's up to the client to control the delay.) // Of course, you can also put a delay here, if you want. } } while ( inTxt != null ); } catch ( Exception e ) { System.out.println( "Error in connection to " + s.getInetAddress() + ": " + e ); } } // End run } //End class SConnectionThread
[email protected]
14/21
Network
Modern Programming Languages
ตัวอยาง การสราง LoopingClient import java.io.*; import java.net.*; public class LoopingClient { public static void main( String args[] ) { try { // Try to connect to server and port // client thread waits here // until server accepts Socket s = new Socket( "localhost", 8888 ); System.out.println( "Connection established to " + s.getInetAddress() ); // get streams to allow us to read // and write to client BufferedReader in = new BufferedReader( new InputStreamReader( s.getInputStream() )); PrintStream out = new PrintStream( s.getOutputStream() ); // loop String inTxt = ""; for ( int i = 0; i < 100; i++ ) { // write to server String outTxt = "c" + inTxt; System.out.println( "Sending to server: " + outTxt ); out.println( outTxt ); out.flush(); // read from server inTxt = in.readLine(); System.out.println( "Received from server: " + inTxt ); try { Thread.sleep( 100 ); } catch ( Exception e ) { } } // wait for other side to receive // (otherwise, the other side might get an exception when we // close the socket try { Thread.sleep( 1000 ); } catch ( Exception e ) { } in.close(); out.close(); } catch ( Exception e ) { System.out.println( "Error" + e ); } } //End main } //End LoopingClient
[email protected]
15/21
Network
Modern Programming Languages
แบบฝกหัด 1. สรางโปรแกรมสงเมล โดยออกแบบสวนติดตอกับผูใชเอง 2. จงเขียนโปรแกรม Chat Program Server โดยมี GUIs ดังนี้
/* ทําการ import package ที่จําเปนตองใช */
public class Server extends Frame implements ActionListener, WindowListener, Runnable { ServerSocket ss; //กําหนดใชพอรต 7777 Socket sock; BufferedReader br; BufferedWriter bw; TextField text; Button sendBut, exitBut; List list; //List เริ่มตนจะตองมีคําวา “Server up & Listening on port please wait…” public Server(String titleServer) { // Constructor super( setSize(300, 130); setResizable(false); setBackground(
); ); /* ใสสี background สี gray */
/* ทําการจัดวางตําแหนงกราฟก ใหเหมือนกับรูปขางบน (Chat Program Server) */
[email protected]
16/21
Network
Modern Programming Languages
setVisible(true); /* ทําการจัดการ EventListener ของคอมโพเนนทตางๆ */
try { /* ทําการจัดการเกี่ยวกับการติดตอในฝง server */
Thread th = new Thread(this); th.start(); }catch(Exception e){} }
[email protected]
17/21
Network
Modern Programming Languages
public void run() { while (true) { try { list.addItem(br.readLine()); }catch (Exception e){} } } /* ทําการ Overriding Method ของ Interface WindowListener*/ public void actionPerformed(ActionEvent ae) { if (
) System.exit(0);
else { try {
}catch(Exception x){} } } /* ทําการ Overriding Method ของ Interface WindowListener */ /* กําหนดใหกดปุม
แลวทําการปดโปรแกรม */
public static void main(String arg[]) { new Server("
");
} } //End Server Class
[email protected]
18/21
Network
Modern Programming Languages
3. จงเขียนโปรแกรม Chat Program Client โดยมี GUIs ดังนี้
/* ทําการ import package ที่จําเปนตองใช */
public class Client extends Frame implements ActionListener, Runnable { Socket sock; BufferedReader br; BufferedWriter bw; TextField text; Button sendBut, exitBut; List list; public Client(String titleClient) { // Constructor super( ); setSize(300, 130); setResizable(false); setBackground( ); /* ใสสี background สี white */ /* ทําการจัดวางตําแหนงกราฟก ใหเหมือนกับรูปขางบน (Chat Program Client) */
[email protected]
19/21
Network
Modern Programming Languages
setVisible(true); /* ทําการจัดการ EventListener ของคอมโพเนนทตางๆ */
/* ทําการจัดการ EventListener ของ Window โดยการใช WindowAdapter Class */ /* กําหนดใหกดปุม
แลวทําการปดโปรแกรม */
try { /* ทําการจัดการเกี่ยวกับการติดตอในฝง client โดย default IP กําหนดใหเปน 127.0.0.1*/
Thread th = new Thread(this); th.start(); }catch(Exception e){} } public void run() { while (true) { try { list.addItem(br.readLine()); }catch (Exception h){} } }
[email protected]
20/21
Network
Modern Programming Languages
public void actionPerformed(ActionEvent ae) { if (
) System.exit(0);
else { try {
}catch(Exception x){} } public static void main(String arg[]) { new Client("
");
} } //End Client
[email protected]
21/21