Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
บทท 18
การเขยนโปรแกรมท างานบนระบบเครอขาย Java Network Programming ปจจบนระบบการตดตอสอสารผานเครอขายไดมบทบาทส าคญจนถอไดวาเปนความจ าเปนทขาดไมได เมอพจารณาจากกจกรรมในการใชงานคอมพวเตอรในแตละวนประกอบดวย การตรวจ Email การคนหาขอมลทางเวบไซตตางๆ หรอ การ Download ขอมลเปนตน กจกรรมเหลานจ าเปนตองอาศยการเชอมตอกบระบบเครอขาย ดงนนการเขาใจการท างานของระบบเครอขายและสามารถพฒนาโปรแกรมทใชในการตดตอสอสารระหวางเครองคอมพวเตอรเปนเรองทนาทาทายและนาสนใจเปนอยางยง ในบทนกลาวถงการเขยนโปรแกรมเครอขายเบองตนโดยใช Socket ซงไมครอบคลมถงการเขยนโปรแกรมเครอขายแบบอนๆ ใน Java การเขยนโปรแกรมโดยใช Socket ผอานไมจ าเปนตองเขาใจรายละเอยดวาระบบเครอขายมการท างานอยางไร เพยงแตเขาใจวาจะน า Socket ไปใชงานไดอยางไร กสามารถเขยนโปรแกรมเครอขายได อยางไรกตามถาเขยนโปรแกรมโดยไมเขาใจหลกการพนฐานการท างานของระบบเครอขายแลว กรณทเกดปญหาขน อาจท าใหไมสามารถวเคราะหและแกไขปญหานนไดอยางมประสทธภาพ ดงนนเพอใหเกดความเขาใจระบบการสงขอมลในเครอขายอยางเบองตน จงขอกลาวถงการท างานของระบบเครอขาย ดงตอไปน TCP/IP ค าวาเครอขาย หมายถงระบบซงประกอบดวยคอมพวเตอรมากกวาหนงเครองเชอมตอถงกนโดยใชสายหรอไรสาย สามารถรบและสงขอมลระหวางกนได การออกแบบระบบเครอขายมปญหาททาทายนกคอมพวเตอร คอ ท าอยางไรใหคอมพวเตอรทมหลายประเภทสามารถตดตอสอสารกนได เนองจากคอมพวเตอรแตละประเภทมการจดการขอมลทไมเหมอนกน เชน แฟมขอมลทจดเกบในเครอง PDA อาจไมเหมอนในเครอง Supercomputer หรอ รหสตวอกษรทมหลายแบบ เชน ASCII หรอ UNICODE ในการสงขอมลถาใชรหสตวอกษรทตางกน ท าใหการรบสงขอมลผดพลาดได ดงนนมาตรฐานกลาง หรอ Protocol เปนสงส าคญทจะท าใหเครองคอมพวเตอรทกประเภทสามารถตดตอสอสารกนได ค าวา Protocol หมายถงขอตกลง หรอ ขอก าหนด เพอใหคอมพวเตอรสามารถตดตอสอสารกนได Protocol มอยหลายชนด แต Protocol ทใชมากทสดคอ TCP/IP (Transport Control Protocol/Internet Protocol) ซงเปนขอก าหนดเพอใหคอมพวเตอรทวโลกสามารถตดตอสอสารกนได TCP/IP แบงเปน 4 ชนคอ
1. Host-To-Network Layer กลาวถงการสงสญญาณไปในตวกลาง เชน ถาตวกลางเปนสายไฟ ในชนนตองก าหนดมาตรฐานของแรงดนไฟฟา หรอ ตวกลางเปนอากาศ ตองมการก าหนดคลนความถวทยทใช รวมถง Protocol ตางๆ ทท าใหสามารถสงขอมลไปในระบบเครอขายทมโครงสราง (Topology) ทแตกตางกนได เชน Ethernet หรอ FDDI ดงนนสวนประกอบในชนนเปน Hardware สวนใหญ เชน Network Interface Card
2. Internet Layer ระบบอนเตอรเนตเปรยบเหมอนใยแมงมมซงดซบซอนและวนวาย เนองจากมอปกรณเครอขายทรบสงขอมลจ านวนมากในระบบอนเตอรเนต ผอานอาจนกถงการเดนทางในกรงเทพมหานครฯ
368 การเขยนโปรแกรมภาษา Java
ซงมเสนทางจ านวนมาก ทงทางดวน ทางหลก และ ทางลด ดงนนการเดนทางจ าเปนตองมการวางแผนเสนทางกอน เพอใหเดนทางถงจดหมายปลายทางเรวทสด ในระบบอนเตอรเนตเชนกน การหาเสนทางทดทสดใหกบขอมลทสงจากผสงไปยงผรบ เปนหนาทส าคญของ Internet Layer
3. Transport Layer รบผดชอบในการตรวจสอบวาขอมลทสงไปถงผรบจรง และเรยงล าดบขอมลอยางถกตองในกรณทมขอมลจ านวนมาก รวมทงควบคมความเรวในการรบสงขอมล เนองจากความหลากหลายของเครองคอมพวเตอร ท าใหความสามารถในการรบสงขอมลไมเทากน เชน เครองคอมพวเตอรความเรวสงอาจสงขอมลไดเรว เมอเปรยบเทยบกบเครองคอมพวเตอรทมความเรวต าและหนวยความจ านอย ดงนนหนาทของ Transport จงตองควบคมความเรวและจ านวนของขอมลในรบสงแตละครง
4. Application Layer เปนชนทจดการโปรแกรมทใหบรการผใชงาน เชน จดหมายอเลกทรอนกส การสงแฟมขอมลผานระบบเครอขาย หรอ ระบบเวบ เปนตน
ภาพท 8.1 แสดงชนของ TCP/IP เหตผลทมการแบงการท างานของ TCP/IP เปนล าดบชน ขอยกตวอยางเปรยบกบวธการเขยนโปรแกรมคอ การเขยนโปรแกรมขนาดใหญและไมสรางฟงกชนเลย อาจท าใหโปรแกรมนนมความซบซอนและยากตอการแกไขโปรแกรม แตถาสรางใหโปรแกรมประกอบไปดวยฟงกชนยอยๆ จ านวนมาก อาจท าใหโปรแกรมมขนาดใหญขนแตโปรแกรมนนมระเบยบมากขนดวย ซงท าใหงายในการแกไขโปรแกรม ในการออกแบบระบบ TCP/IP กเชนกน เนองจากระบบตดตอสอสารมความซบซอนสง การแบงระบบออกเปนล าดบชนจะท าใหการสรางระบบงายขน ในกรณทมความผดพลาดเกดขนในระบบ การตรวจสอบแกไขท าไดงาย และสามารถเปลยนแปลงแกไขสวนใดสวนหนงในล าดบชน จะไมสงผลกระทบการล าดบชนอน เชน ถาชนท 1 Host-To-Network ใชงานไมได ผดแลระบบสามารถเปลยนอปกรณในชนท 1 ได โดยไมสงผลกระทบกบชนอน IP Address การสงขอมลไปยงผรบ ผสงจ าเปนตองทราบทอยของผรบ ซงทอยนตองไมซ ากนทวโลก IP Address ในระบบอนเตอรเนตเปนเลขฐานสองจ านวน 32 บต เพอความสะดวกในการใชงาน สามารถเขยนเปนเลขฐานสบไดสชดๆ ละ 8 บต (Dotted-Decimal Notation) ดงตวอยางเชน
203.18.33.6
Application Layer
Transport Layer
Internet Layer
Host-To-Network Layer
การเขยนโปรแกรมภาษา Java 369
Server
Http: Port 80
SMTP: Port 25
Telnet: Port 23
Time: Port 37
Echo: Port 7
Internet Explorer
Sending Email
Network Interface Card
เพอผใชงานสามารถจดจ าทอยนไดงายขน จงมการสรางระบบการเปลยนชอใหเปน IP Address (Domain Name Server) ท าใหผใชงานสามารถใชชอทสอความหมายแทนการใชทอย IP address ได เชน www.bu.ac.th หรอ sun.java.com Port ปจจบนคอมพวเตอรสามารถท างานไดมากกวาหนงงานในเวลาเดยวกน (Multitasking) หมายความวา ผใชงานสามารถรบสงจดหมายอเลกทรอนกส ดขอมลในเวบไซต หรอ สามารถ Download ขอมลจากระบบเครอขายไดพรอมกน ดงนนการตดตอสอสารจ าเปนตองมการระบวาขอมลทรบสงนนใชกบโปรแกรมใดในเครอง การระบวาขอมลเปนของโปรแกรมใดเรยกวาการระบ Port ตวอยางของ Port ดงภาพท 18.2
ภาพท 18.2 แสดง Port การตดตอสอสาร
จากภาพท 18.2 เครองผใหบรการ (Server) สามารถรองรบการท างานผานระบบเครอขายไดหลายโปรแกรม เมอมผขอใชบรการ (Client) รองขอบรการจากผใหบรการ ผใหบรการจ าเปนตองทราบวาเครองขอบรการตองการขอมลใด โดยผานการระบหมายเลขของ Port
หมายเลขทต ากวา 1024 ถกใชส าหรบโปรแกรมทรจกทวไป เชน เวบ หรอ Telnet ดงนนผเขยนโปรแกรมจ าเปนตองใช Port ตงแตหมายเลข 1024 ถง 65535 เทานน (Port มความกวาง 16 บต) และผขอใชบรการจ าเปนตองทราบหมายเลขในการตดตอสอสารกบเครองใหบรการดวย ตวอยางตอไปแสดงการใชค าสง Telnet เพอเขาสระบบ Email ของเครองใหบรการ
370 การเขยนโปรแกรมภาษา Java
ภาพท 18.3 แสดงการใชค าสง Telnet เพอตดตอ Port 25 หรอ Email service
ตารางท 18.1 แสดงบรการตางๆ แลหมายเลข Port tcpmux 1/tcp echo 7/tcp discard 9/tcp systat 11/tcp daytime 13/tcp netstat 15/tcp chargen 19/tcp ftp-data 20/tcp ftp 21/tcp telnet 23/tcp smtp 25/tcp mail time 37/tcp timserver whois 43/tcp nicname domain 53/tcp
การเขยนโปรแกรมเครอขายโดยใช Socket ในฝงผขอใชบรการ Socket เปนโครงสรางการเขยนโปรแกรมเครอขาย (Networking Framework) ทนยมใชมากทสด สรางขนโดยกลมนกวจยทเรยกตวเองวา Berkeley Unix วตถประสงคของการสราง Socket เพอใหนกเขยนโปรแกรมสามารถพฒนาโปรแกรมทางเครอขายไดงายชน โดยทไมจ าเปนตองสนใจในรายละเอยดของการเชอมตอทเกดขนจรง ผเขยนโปรแกรมสามารถเขยนโปรแกรมเพอรบสงขอมลผาน Socket ไดทนทหลงจากทมการเปดใชงาน
การเขยนโปรแกรมภาษา Java 371
Socket สวนการรบสงขอมลผาน Socket เหมอนการเขยนหรออานขอมลจากแฟมขอมลในลกษณะของ Byte Stream ขนตอนการสราง Socket ตดตอสอสาร ส าหรบเครองผขอใชบรการมดงตอไปน
1. สราง Socket ตดตอไปยงเครองผใหบรการ 2. สราง InputStream และ OutputStream จาก Socket ทเปดไว 3. เขยนและอานขอมลจาก Stream ทไดมาในขอสอง ตาม Protocol ของผใหบรการ 4. เมอจบโปรแกรม ปด InputStream และ OutputStream 5. ปด Socket
การสรางคลาส Socket ตองระบหมายเลข Port และผใหบรการ หรอ Host ซงมคาเปน String หรอเปนคลาส InetAddress (IP address) ซงใช Method ในทชอ public static InetAddress getByName(String host) ในการหาคา InetAddress ได
การสราง Socket ทดานผขอใชบรการ จ าเปนตองจบสญญาณ Exception จ านวน 2 คาคอ UnknownHostException และ IOException import java.net.*;
try {
// ระบ host และหมายเลข Port Socket toBu = new Socket (“www.bu.ac.th”, 80);
}
catch (UnknownHostException e) {
System.out.println( e.getMessage() );
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
// หรอสามารถใชคลาส InetAddress แทนชอ Host ได try {
InetAddress ipHost = InetAddress.getByName (“www.google.com”);
// ระบ host และหมายเลข Port Socket toBu = new Socket (ipHost, 80);
}
catch (UnknownHostException e) {
System.out.println( e.getMessage() );
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
ในกรณทไมทราบชอของ Host แตทราบ IP Addressทตองการตดตอ สามารถใชคลาส InetAddress ชวยในการเปลยน IP Address ใหเปน InetAddress ได ดงตวอยางตอไป
372 การเขยนโปรแกรมภาษา Java
Server
Internet Explorer
Port 80Port 3333
Server
Internet Explorer
Port 80Port 3333
Port 36000
Server
Internet Explorer
Port 80
Port 4444
ServerInternet Explorer
Port 80
Port 3333
Port 36000
Internet Explorer
Port 3333 Port 36000
Internet Explorer
Port 4444
Port 15800
import java.net.*;
try {
InetAddress ipHost = InetAddress.getByName (“203.18.50.235”);
// ระบ host และหมายเลข Port Socket toBu = new Socket (ipHost, 80);
}
catch (UnknownHostException e) {
System.out.println( e.getMessage() );
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
เมอท าการสราง Socket ตดตอไปทเครองใหบรการแลว เครองใหบรการจะสราง Port ใหมเพอตดตอกบเครองขอใชบรการ เพอใหเครองใหบรการสามารถรองรบการตดตอสอสารกบเครองขอใชบรการเครองอนๆ ตอไป ดงภาพท 18.4 และ 18.5
ภาพท 18.4 แสดงการสราง Port ใหมส าหรบเครองขอใชบรการ
ภาพท 18.5 แสดงหมายเลขของ Port ในกรณทมเครองขอใชบรการ 2 เครอง
การเขยนโปรแกรมภาษา Java 373
Server
Internet Explorer
Port 80Port 6666
โดยปกตหมายเลข Port ในฝงผขอใชบรการจะถกสรางโดยอตโนมตจาก Port ทยงไมถกใชงาน ในรป 18.4 และ 18.5 เปนการสมมตหมายเลข Port ของเครองผขอใชบรการเปน 3333 และ 4444 ซงอาจมการเปลยนแปลงไดเมอมการเปด Socket ใหม ถาตองการระบหมายเลข Port ในเครองผขอใชบรการดวย สามารถใช Constructor รปแบบตอไปนได public Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException
ตวแปร localAddr สามารถใชค าสง InetAddress.getLocalHost() ได ดงตวอยาง InetAddress localAddr = InetAddress.getLocalHost();
ตวอยางตอไปแสดงวธการใชค าสงทสราง Socket โดยก าหนด Local Port ของเครองผขอใชบรการ import java.net.*;
try {
InetAddress ipHost = InetAddress.getByName (“203.18.50.235”);
InetAddress localAddr = InetAddress.getLocalHost();
Socket toBu = new Socket (ipHost, 80, localAddr, 6666);
}
catch (UnknownHostException e) {
System.out.println( e.getMessage() );
}
catch (IOException e) {
System.out.println( e.getMessage() );
}
ภาพท 18.6 แสดงการสรางโดยระบหมายเลข Port ทเครองผขอใชบรการ
โปรแกรม PortScan.java แสดงการตรวจสอบวาเครองใหบรการมการเปดใหบรการใดบาง หลกการท างานคอสราง Socket โดยก าหนดหมายเลขของ Port ไปทเครองผใหบรการ ในกรณทเปดไมได Socket จะสง Exception ชอ IOException ถาเปด Port ไดจะไมมการสง Exception ดงนนผเขยนโปรแกรมสามารถดกจบ Excetion ไดในกรณทไมสามารถเปด Port ได
374 การเขยนโปรแกรมภาษา Java
import java.net.*;
import java.io.*;
public class PortScan {
public static void main(String[] args)
{
// ในกรณทผสงงานไมไดปอนชอของ Host ทเปน Server // ใหตงคาเปนเครองผขอบรการเอง (Local Host) String host="localhost"; System.out.println("This program will scan port available on a server");
if(args.length > 0) {
host = args[0];
}
for(int i=1; i<1024; i++) {
try {
InetAddress ipHost = InetAddress.getByName(host);
Socket s = new Socket(ipHost, i);
System.out.println("There is a service on port " + i +
" in " + host);
s.close();
}
catch (UnknownHostException e){
System.out.println(e.getMessage());
}
catch(IOException e) {}
}
}
}
---------- Java Output----------
c:\java PortScan www.bu.ac.th
This program will scan port available on a server
There is a service on port 7 in www.bu.ac.th
There is a service on port 9 in www.bu.ac.th
There is a service on port 13 in www.bu.ac.th
There is a service on port 19 in www.bu.ac.th
There is a service on port 21 in www.bu.ac.th
There is a service on port 23 in www.bu.ac.th
There is a service on port 25 in www.bu.ac.th
There is a service on port 37 in www.bu.ac.th
There is a service on port 79 in www.bu.ac.th
There is a service on port 80 in www.bu.ac.th
There is a service on port 110 in www.bu.ac.th
There is a service on port 512 in www.bu.ac.th
There is a service on port 513 in www.bu.ac.th
There is a service on port 514 in www.bu.ac.th
There is a service on port 540 in www.bu.ac.th
There is a service on port 587 in www.bu.ac.th
There is a service on port 665 in www.bu.ac.th
There is a service on port 898 in www.bu.ac.th
การเขยนโปรแกรมภาษา Java 375
DaytimeClient
Open Socket on
Port 13
getInputerStream
Read from
InputStream
Display and Close
Socket
End
DaytimeClient โปรแกรม DaytimeClient.java (Port หมายเลข 13) แสดงการตดตอสอสารระหวางผขอใชบรการกบผใหบรการ เพอใหขอมลเกยวกบเวลา หลกการท างานโดยเมอผขอบรการเชอมตอไปทเครองใหบรการโดยใช Socket แลว เครองใหบรการจะสงขอมล String ของเวลา ดงตวอยางตอไป C:\telnet www.bu.ac.th 13
Tue Sep 9 17:34:14 2003
ภาพท 18.7 แสดง Flowchart ของ DaytimeClient
376 การเขยนโปรแกรมภาษา Java
โปรแกรม DaytimeClient.java แสดงการสรางโปรแกรมส าหรบผขอบรการขอขอมลเวลาของเครองใหบรการ import java.net.*;
import java.io.*;
public class DaytimeClient {
public static void main(String[] args)
{
String host="localhost";
System.out.println("This program will get time on a server");
if(args.length > 0) {
host = args[0];
}
try {
InetAddress ipHost = InetAddress.getByName(host);
Socket socket = new Socket(ipHost, 13);
// วธการใช BufferredReader อานไดจากบทท 10 BufferedReader input = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
System.out.println("Output time from the " + host);
System.out.println( input.readLine() );
socket.close();
}
catch (UnknownHostException e){
System.out.println(e.getMessage());
}
catch(IOException e) {}
}
}
---------- Java Output---------- C:\java Daytime www.bu.ac.th
This program will get time on a server Output time from the www.bu.ac.th Tue Sep 9 17:49:30 2003 EchoClient บรการ Port ท 7 (ตารางท 18.1) ทเครองใหบรการ ท างานโดยรบขอมล String จากเครองผขอบรการและสงขอความทไดรบมานนกบไปใหเครองผขอบรการ ดงโปรแกรม EchoClient.java import java.net.*;
import java.io.*;
public class EchoClient {
public static void main(String[] args) {
String host="localhost";
System.out.println("This program will echo what you “+
”have typed from a server");
System.out.println("Please type \"END\" to quit the program");
การเขยนโปรแกรมภาษา Java 377
if(args.length > 0) {
host = args[0];
}
try {
InetAddress ipHost = InetAddress.getByName(host);
Socket socket = new Socket(ipHost, 7);
// เปด Input Stream จากเครองใหบรการ BufferedReader input = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
// เปด Output Stream ไปทเครองใหบรการ PrintWriter output = new
PrintWriter(socket.getOutputStream(), true);
// เปด BufferedReader เพออานขอมลจากแปนพมพ BufferedReader keyboard = new BufferedReader (
new InputStreamReader(System.in));
String dataIn;
do{ // วนเพออานขอมลจากแปนพมพ แลวสงไปทเครองใหบรการ dataIn = keyboard.readLine();
output.println(dataIn);
System.out.println("From server: " +input.readLine());
} while ( !dataIn.equals("END") ); // จนกระทงผใชงานพมพ END
socket.close();
}
catch (UnknownHostException e){
System.out.println(e.getMessage());
}
catch(IOException e) {}
}
}
---------- Java Output----------
การเขยนโปรแกรมเครอขายโดยใช ServerSocket ในฝงผใหบรการ เครองผใหบรการตองมความสามารถรบการตดตอกบเครองขอบรการไดหลายเครองพรอมกน ดงนนการเขยนโปรแกรมส าหรบเครองใหบรการ จ าเปนตองใชคลาส Thread เพอใหเครองใหบรการสามารถสราง Thread รองรบการเชอมตอจากเครองขอบรการแตละเครองได ดงภาพท 18.8
378 การเขยนโปรแกรมภาษา Java
Create a
ServerSocket
Accept a
connection from
Client
Server
Using Thread to
communicate with
Client
Create Thread
Loop
Wait for other
connections
เมอเครองใหบรการไดรบการรองขอการเชอมตอจากเครองขอบรการแลว เครองใหบรการจะสราง Server Thread เพอท าหนาทตดตอกบเครองขอบรการโดย Server Thread ทถกสรางมาจะท าการหา Port ทวางส าหรบตดตอกบเครองขอบรการนนๆ ตอไป
ภาพท 18.8 แสดง Flowchart การท างานของเครองใหบรการ
ขนตอนการสรางโปรแกรมฝงผใหบรการ 1. สราง ServerSocket โดยระบหมายเลข Port ทใช 2. เรยกใช Method accept() เพอรองรบการเชอมตอจากเครองขอบรการ 3. สราง Thread เพอใชในการจดการการเชอมตอ และใชคา Socket ทสงกลบมาจาก Method accept() มา
ใชในการสราง InputStream และ OutputStream 4. เขยนและอานขอมลจาก Stream ทไดมาตาม Protocol ของผใหบรการ 5. เมอจบโปรแกรม ปด InputStream และ OutputStream และ Socket ทเชอมกบเครองขอบรการ 6. กลบไปท างานในขนตอนท 2 ตอไป ส าหรบรองรบการเชอมตอไปเครองขอบรการเครองอนตอไป
ขนท 1 try{
int port = 3333;
ServerSocket server = new ServerSocket(port);
} catch (IOException e) {
System.out.println(“Server could not use the port”);’
}
การเขยนโปรแกรมภาษา Java 379
ขนท 2 3 และ 6 while (true) {
Socket connectionTo = server.accept();
//สราง Thread เพอรบการเชอมตอกบเครองขอบรการ new ServerThread(connectionTo).start();
}
ขนท 4 และ 5 // สรางคลาส ServerThread import java.net.*;
import java.io.*;
class ServerThread extends Thread{
private Socket connection;
private PrintWriter out;
private BufferedReader in;
public ServerThread(Socket connection) {
this.connection = connection;
try {
out = new PrintWriter(connection.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader (
connection.getInputStream() ));
}
catch(IOException e) {
System.out.println(
"Error while get input and output stream from socket");
System.exit(1);
}
}
public void run() {
//เขยนโปรแกรมเพอตอบโตกบเครองขอบรการทน out.close();
in.close();
connection.close();
}
}
ตวอยางโปรแกรม Chat โปรแกรม ChatClient.java และ ChatServer.java จ าลอง Chat Room ซงสามารถมผสนทนาไดมากกวาหนงคน โดยหลกการท างานมดงน เมอโปรแกรม ChatServer ไดรบการรองขอการเชอมตอจาก ChatClient โปรแรม ChatServer จะสราง ServerThread รองรบการเชอมตอนน ซงทกๆ ServerThread จะอยใน ThreadGroup เดยวกน เมอการเชอมตอสมบรณแลว ทง ChatServer และ ServerThread จะมการตดตอสอสารโดยผาน InputStream และ OutputStream ถาผใชงานพมพขอความท ChatClient ขอความนนจะถกสงมาท ServerThread และ ServerThread จะท าการสงขอความนไปให ChatClient ทกตวเพอใหแสดงขอความทไดรบ
380 การเขยนโปรแกรมภาษา Java
ChatServer ServerThread
ServerThread
ServerThread ChatClient
ChatClient
ChatClient
Thread
Connection
Connection
Connection
Thre
ad
Thread
เมอ ServerThread ไดรบขอมลจาก ChatClientตวใดตวหนง แลว ServerThread ตองสงขอมลไปใหServerThread ททำงานอยทงหมด โดยใช ThreadGroupเพอให ServerThread สงขอมลนตอไปไยง ChatClientของตนเอง
ภาพท 18.9 แสดงภาพการท างานของโปรแกรม Chat
import java.net.*;
import java.io.*;
class ChatServer {
public static void main(String[] args) {
boolean forever = true;
ServerSocket serverSocket = null;
// สราง ThreadGroup ThreadGroup myThreadGroup =
new ThreadGroup("Contain chat client threads");
try {
// สราง ServerSocket เพอรองรบการตดตอจากเครองขอบรการ serverSocket = new ServerSocket(3333); System.out.println("Server started. Waitting for client");
// วนลปไมรจบ while (forever) {
//ใชค าสง accept() เมอมการรองขอจากเครองขอบรการ Socket connectionTo = serverSocket.accept();
การเขยนโปรแกรมภาษา Java 381
System.out.println("Received a connection from a client");
// สราง ServerThread เพอรองรบการเชอมตอ new ServerThread(
myThreadGroup, connectionTo).start();
}
}
catch (IOException e) {
System.out.println("Could not use this port");
System.exit(1); }
}
}
โปรแกรม ServerThread.java ท าหนาทจดการ การสงขอมลระหวาง ChatClient สวน ServerThread สามารถมไดมากกวาหนงขนอยกบจ านวน ChatClient ทเชอมตอ เชนถาม ChatClient 3 โปรแกรม ServerThread จะม 3 โปรแกรมดวย เมอ ServerThread ตวใดไดรบขอมลตวอกษรจาก ChatClient แลว ServerThread นนจะตองท าการสงขอมลไป ServerThread ทงหมดทท างานอยในขณะนน เพอใหแสดงขอความสนทนาท ChatClient ทกตว import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ServerThread extends Thread{
private Socket connection;
private PrintWriter output;
private BufferedReader input;
private ThreadGroup clientGroup;
public ServerThread(ThreadGroup threadGroup, Socket connection) {
// เรยก Constructor ของคลาส Thread // เพอก าหนดใหอยใน ThreadGroup เดยวกน super(threadGroup, "Connection to ChatClient");
clientGroup = threadGroup;
this.connection = connection;
try {
// สราง Output และ Input Stream กบ ChatClient output = new PrintWriter(connection.getOutputStream(), true);
input = new BufferedReader(new InputStreamReader (
connection.getInputStream() ));
}
catch(IOException e) {
System.out.println(
"Error while getting input and output stream from socket");
}
}
public void run() {
try {
// อานขอมลจาก ChatClient String data = input.readLine();
382 การเขยนโปรแกรมภาษา Java
while( data != null ) {
System.out.println(data);
// หาจ านวนของ ServerThread ทท างานอย // เพอใชในการสงขอความทไดรบจาก ChatClient // ไปท ServerThread อนๆ int numOfThreads = clientGroup.activeCount();
thread.sendToAllClients(data) ;
clientGroup.enumerate(listOfThreads);
for (int i = 0; i < numOfThreads; i++){
ServerThread thread = (ServerThread) listOfThreads[i];
// สงขอความทไดรบจาก ChatClient ไปทก ServerThread thread.sendToAllClients(data) ;
}
data = input.readLine();
}
}
catch(IOException e) {
System.out.println("Client has been disconnected");
}
}
public void sendToAllClients(String data) {
output.println(data);
}
}
สวนโปรแกรม ChatClient.java มลกษณะเปน Graphic User Interface โดยมชองใหผใชงานพมพขอความ และมปม Send เพอสงขอความไปท ServerThread import java.net.*;
import java.io.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class ClientFrame extends JFrame implements ActionListener{
private PrintWriter output;
private BufferedReader input;
private JButton sendButton, exitButton;
private JTextArea display;
private JTextField dataIn, userName;
//Constructor ของ ClientFrame public ClientFrame(String host) {
// เปดการเชอมตอไปท ChatServer หมายเลข Port 3333 // และสราง Input และ Output Stream try {
InetAddress ipHost = InetAddress.getByName(host);
Socket socket = new Socket(ipHost, 3333);
input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
output = new PrintWriter(socket.getOutputStream(), true);
การเขยนโปรแกรมภาษา Java 383
}
catch (UnknownHostException e){
System.out.println("Unknow host");
System.exit(1);
}
catch(IOException e) {
System.out.println("Error open connection");
int width = 500, height = 400;
}
// ก าหนดรายละเอยดของ JFrame Toolkit tk = getToolkit();
Dimension screen = tk.getScreenSize();
int width = 500, height = 400;
setBounds( (screen.width - width)/2, (screen.height - height)/2,
width, height);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// ชองส าหรบผใชโปรแกรมพมพขอความ dataIn = new JTextField(20);
// ชอของผใชงาน userName = new JTextField(5); userName.setText("Name");
// ปม Send และ Exit sendButton = new JButton("Send text");
exitButton = new JButton("Exit");
// เพม ActionListener ใหกบปม Send และ Exit sendButton.addActionListener(this);
exitButton.addActionListener(this);
// สราง JPanel เพอบรรจชองส าหรบพมพ ชอ และปมตางๆ JPanel p = new JPanel();
p.setLayout(new FlowLayout());
p.add(dataIn);
p.add(sendButton);
p.add(exitButton);
p.add(userName);
// สราง JTextArea เพอใชในการแสดงค าสนทนา display = new JTextArea();
Container c = getContentPane();
c.setLayout( new BorderLayout() );
// เพมสวนประกอบทงหมดไปท JFrame c.add(display, BorderLayout.CENTER);
c.add(p, BorderLayout.SOUTH);
setVisible(true);
}
public void actionPerformed (ActionEvent e) {
JButton src = (JButton) e.getSource();
if(src == sendButton) { // เมอผใชงานกดปม Send
if( dataIn.getText().equals("") ) return; // ตรวจสอบวาไมใชชองวาง //สงขอความไปท ServerThread output.println(userName.getText() + ": " + dataIn.getText());
dataIn.setText("");
384 การเขยนโปรแกรมภาษา Java
dataIn.requestFocus(true);
}
else
System.exit(0);
}
// Method นไวส าหรบรบขอมลจาก ServerThread และแสดงผลไปท JTextArea public void process() {
String data;
while (data != null);
do{
data = input.readLine();
display.append(data+"\n");
}
while (data != null);
}
catch(IOException e) {
System.out.println("Error while reading from server");
}
}
}
public class ChatClient{
public static void main(String[] args){
String host="localhost";
if(args.length > 0) {
host = args[0];
}
ClientFrame client = new ClientFrame(host);
client.process();
}
}
ภาพท 18.10 แสดงผลลพธจากโปรแกรม ChatServer.java และ ChatClient.java
การเขยนโปรแกรมภาษา Java 385
สรป การตดตอสอสารผานระบบเครอขายเปนสงจ าเปนส าหรบระบบคอมพวเตอรมากขนเรอยๆ เนองจากโปรแกรมสวนใหญท างานผานระบบเครอขาย เชนการจองตวเครองบนผานระบบอนเตอรเนต หรอการลงทะเบยนเรยนออนไลน ซงตองอาศยระบบเครอขายทงสน ปจจบนถามเครองคอมพวเตอรแตไมเชอมตอกบระบบอนเตอรเนต เครองคอมพวเตอรนนคงไมมผใดอยากใชงาน ปจจบน ขอก าหนด TCP/IP เปนทนยมใชอยางแพรหลาย เปนขอตกลงเพอใหคอมพวเตอรทวโลกสามารถตดตอสอสารกนได
การสรางโปรแกรมส าหรบระบบเครอขายในภาษา Java นนงายกวาภาษาอน เนองจากการใชค าสงทไมซบซอน วธการสรางโปรแกรมใชคลาส Socket และ ServerSocket ส าหรบเครองขอใชบรการและเครองใหบรการตามล าดบ
386 การเขยนโปรแกรมภาษา Java
แบบฝกหดทายบทท 18
1. อธบายหนาททง 4 ล าดบชนของ TCP/IP 2. อธบายขนตอนการเขยนโปรแกรมฝงผใหบรการโดยใช ServerSocket 3. IP Adress และ Port คออะไร มความส าคญอยางไร
Programming Problems
1. จงเขยนโปรแกรมเกมโอเอกซใหท างานในระบบเครอขาย โดยมผเลนเกมอยคนละเครองคอมพวเตอร 2. จงพฒนาโปรแกรมเกม Cross Word ส าหรบระบบเครอขาย 3. จงพฒนาโปรแกรมการรบสงแฟมขอมลผานระบบเครอขาย 4. จงพฒนาโปรแกรม Web Server อยางงาย (สามารถใช JEditorPane หรอ JTextPane ในการแสดงผล
ลพธจากแฟมขอมล HTML ได)