ĐA CS Ngành Mạng
MỞ ĐẦU
Lập trình mạng và hệ điều hành là những kiến thức tối quan trọng trong hành
trang của sinh viên chuyên ngành công nghệ thông tin. Có thể nói rằng đây là hai
khía cạnh rất đặc biệt vì một bên ở mức khá cao còn một bên ở mức khá thấp. Sự
kết hợp của hai phần này tạo ra một trải nghiệm lập trình rất đặc biệt cho sinh viên,
để hình dung được cái nhìn tổng quát của một hệ thống điển hình.
Báo cáo này trình bày cho những gì em đã học được và vẫn dụng vào đồ án trong
kì này, với sự hướng dẫn của GVHD. em sẽ cắt và giản, trình bày gọn gang, súc tích
qua những đoạn mã và hình ảnh chạy chương trình. tập trung vào những gì em hiểu
được và sẽ ghi vào báo cáo này.
Tuy em đã làm cẩn thận nhưng sẽ còn những sai sót không không muốn, em rất
mong sự góp ý của quý thầy cô trong khoa để em rút kinh nghiệm.
Mọi hình ảnh, mã nguồn trong báo cáo đều do bản thân em tự làm, không sao
chép toàn bộ từ bất cứ nguồn nào.
Em xin chân thành cảm ơn.
Đà Nẵng, tháng 05 năm 2017.
Sinh viên
Nguyễn Đình Phát
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
1
ĐA CS Ngành Mạng
MỤC LỤC
PHẦN 1: ĐỒ ÁN MẠNG
1.1 GIỚI THIỆU
Đề Tài Mạng: Truyền Tải Tập Tin Qua Mạng Sử Dụng Socket
Viết chương trình theo mô hình Client-Server (sử dụng TCP hoặc UDP), trong đó
Client cung cấp giao diện cho người dùng tương tác với chương trình, Client cung
cấp địa chỉ File được gởi còn Server thực hiện lưu file được nhận vào trong địa chỉ
trong Server.
1.2 CƠ SỞ LÍ THUYẾT
1.2.1 Lí thuyết mạng máy tính
Mạng máy tính là tập hợp các máy tính độc lập, kết nối với nhau thông qua các
đường truyền vật lý và cùng tuân thủ một nguyên tắc truyền thông nào đó. Mạng
phải có giao thức - là một tập hợp các quy tắc chuẩn dành cho việc biểu diễn dữ
liệu, phát tín hiệu, chứng thực và phát hiện lỗi dữ liệu, nhờ đó mà các máy tính có
thể kết nối và trao đổi thông tin với nhau một cách tin cậy, thậm chí trên các đường
truyền không được hoàn hảo. Một số giao thức như: TCP/IP, UDP, HTTP, FTP,
SMTP, POP3,…
Có rất nhiều tiêu chí để phân loại mạng máy tính, có thể dựa vào loại máy kết
nối, có thể dựa vào đặc điểm đường truyền và cũng có thể dựa vào nguyên tắc
truyền thông như: WAN, LAN, GAN, Intranet, Internet.
Theo đó cũng có nhiều mô hình mạng khác nhau như mạng tuyến tính (bus),
mạng hình sao (star), mạng hình vòng (ring). Mạng máy tính có thể được khai thác
dựa vào 2 mô hình ứng dụng chính: mô hình mạng ngang hàng (P2P) và mô hình
khách-chủ (Client-Server). Phạm vi đề tài chính là thực hiện trên mô hình ClientServer.
1.2.2 Mô hình Client-Server
Mô hình client-server là một mô hình nổi tiếng trong mạng máy tính, được áp
dụng rất rộng rãi và là mô hình của mọi trang web hiện có. Ý tưởng của mô hình
này là máy khách gửi một yêu cầu (request) để máy chủ, máy chủ sẽ xử lý và trả kết
quả về cho máy khách (response). Trong này một Server có thể phục vụ rất nhiều
Client.
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
2
ĐA CS Ngành Mạng
1.2.3 Ngôn ngữ Java và lập trình socket
Java là một ngôn ngữ lập trình hướng đối tượng, ra mắt năm 1991 bởi Sun
Microsystems với cú pháp lấy cảm hứng từ ngôn ngữ C++ trước đó. Chương trình
Java có tính tương thích cao với nhiều hệ thống do mã nguồn được biên dịch thành
mã trung gian byte-code và chạy trên bất cứ hệ thống nào hỗ trợ môi trường thực thi
(runtime environment) cho nó. Ban đầu Java cũng có tính ỳ ạch nhưng những bản
cập nhật sau đã cải thiện tốc độ nó ngang tầm với Python, PHP cho nên gần đây
Java đang nổi lên như một hiện tượng trong giới lập trình.
Java hỗ trợ lập trình mạng, gói java.net của J2SE API chứa một tập hợp các
classes và interfaces khá chi tiết về giao tiếp tầm thấp, cho phép viết các chương
trình và giải quyết vấn đề một cách nhanh chóng. Nó hỗ trợ hai giao thức mạng phổ
biến TCP/IP và UDP và giao tiếp nhau thông qua Socket.
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
3
ĐA CS Ngành Mạng
Các Socket cung cấp kĩ thuật giao tiếp giữa hai máy tính sử dụng TCP. Một
chương trình Client tạo một socket trên đầu-cuối của giao tiếp và cố gắng để kết nối
socket đó tới một Server. Khi kết nối được tạo, Server tạo một đối tượng Socket trên
đầu cuối của giao tiếp. Client và Server bây giờ có thể giao tiếp bằng việc đọc và
ghi từ Socket.
Lớp java.net.Socket biểu diễn một Socket cho phía client, và lớp
java.net.ServerSocket dành cho chương trình Server để nghe thông tin từ các
Client và thành lập các kết nối với chúng. Các bước sau xảy ra khi thành lập một
kết nối TCP giữa hai máy tính sử dụng Socket:
Server khai báo một đối tượng ServerSocket, biểu thị số hiệu cổng (port) nào để
xuất hiện giao tiếp.
Server gọi phương thức accept() của lớp ServerSocket. Phương thức này đợi tới
khi một Client kết nối với Server trên cổng đã cho.
Trong khi Server đang đợi, một Client khởi tạo một đối tượng Socket, xác định
tên Server và số hiệu cổng để kết nối tới. Nếu giao tiếp được thành lập, bây giờ
Client có một đối tượng Socket có khả năng giao tiếp với Server. Trên phía Server,
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
4
ĐA CS Ngành Mạng
phương thức accept() trả về một tham chiếu tới một socket mới trên Server mà được
kết nối với Socket của Client.
Sau khi các kết nối được thành lập, giao tiếp có thể xảy ra bởi sử dụng I/O
stream. Mỗi Socket có cả một OutputStream và InputStream. OutputStream của
Client được kết nối với InputStream của Server, và InputStream của Client được kết
nối với OutputStream của Server.
1.3 PHÂN TÍCH VÀ THIẾT KẾ GIẢI THUẬT
1.3.1 Sơ đồ hoạt động của hệ thống
Client
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
Server
5
ĐA CS Ngành Mạng
1.4 MÃ NGUỒN CHƯƠNG TRÌNH
1.4.1 Client Java
4.1.1 GUI_Client
package DoAn;
import javax.swing.JOptionPane;
public class GUI_client extends javax.swing.JFrame {
public GUI_client() {
initComponents();
}
BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
text = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
button_truyen = new javax.swing.JButton();
button_reset = new javax.swing.JButton();
jButton1 = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel1.setText("CLIENT");
text.setText("D:\\\\FileClient\\\\zshop.png");
jLabel2.setText("đường dẫn");
button_truyen.setText("Truyền");
button_truyen.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
button_truyenActionPerformed(evt);
}
});
button_reset.setText("Reset");
button_reset.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
button_resetActionPerformed(evt);
}
});
jButton1.setText("Exit");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
6
ĐA CS Ngành Mạng
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADI
NG)
.addGroup(layout.createSequentialGroup()
.addGap(155, 155, 155)
.addComponent(jLabel1)
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGap(35, 35, 35)
.addComponent(jLabel2)
.addGap(18, 18, 18)
.addComponent(text, javax.swing.GroupLayout.DEFAULT_SIZE, 285,
Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addComponent(button_truyen)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(button_reset)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1)
.addGap(12, 12, 12)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new
java.awt.Component[] {button_reset, button_truyen, jButton1});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(29, 29, 29)
.addComponent(jLabel1)
.addGap(72, 72, 72)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASEL
INE)
.addComponent(text, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel2))
.addGap(64, 64, 64)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASEL
INE)
.addComponent(button_truyen)
.addComponent(button_reset)
.addComponent(jButton1))
.addContainerGap(63, Short.MAX_VALUE))
);
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new
java.awt.Component[] {button_reset, button_truyen, jButton1});
pack();
}
private void button_truyenActionPerformed(java.awt.event.ActionEvent evt) {
Client client = new Client();
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
7
ĐA CS Ngành Mạng
String text=this.text.getText();
client.setSourceFilePath(text);
client.setDestinationDirectory(text.substring(0,text.lastIndexOf("\\")-1));
client.createConnection();
JOptionPane.showMessageDialog(null, "da gui xong","Title",
JOptionPane.WARNING_MESSAGE);
}
private void button_resetActionPerformed(java.awt.event.ActionEvent evt)
{
text.setText("");
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new GUI_client().setVisible(true);
}
});
}
private
private
private
private
private
private
javax.swing.JButton button_reset;
javax.swing.JButton button_truyen;
javax.swing.JButton jButton1;
javax.swing.JLabel jLabel1;
javax.swing.JLabel jLabel2;
javax.swing.JTextField text;
}
1.4.2 Client.java
Kết nối đến Server, cho phép người dùng nhập đường dẫn của file cần truyền tới
Server.
package DoAn;
import
import
import
import
import
java.awt.Button;
java.awt.Frame;
java.awt.TextField;
java.io.*;
java.net.*;
public class Client {
private DatagramSocket socket = null;
static int part_number = 0;
static int MAX_BUFFER_SIZE = 63488;//;
// 62*1024
static boolean finish = false;
static long offset = 0;
public void setSocket(DatagramSocket socket) {
this.socket = socket;
}
public void setSourceFilePath(String sourceFilePath) {
this.sourceFilePath = sourceFilePath;
}
public void setDestinationDirectory(String destinationPath) {
this.destinationPath = destinationPath;
}
private FileEvent event = null;
private String sourceFilePath = "D:\\\\FileClient\\\\zshop.png";
private String destinationPath = "D:\\\\FileClient\\\\zshop.png";
private String hostName = "localhost";
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
8
ĐA CS Ngành Mạng
public Client() {
}
public void createConnection() {
try {
socket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName(hostName);
byte[] incomingData = new byte[1024];
finish = false;
part_number = 0;
offset = 0;
while(!finish)
{
System.out.println("[Bat dau] Gui file tu client: Part " + part_number);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(outputStream);
event = getFileEvent();
os.writeObject(event);
byte[] data = outputStream.toByteArray();
System.out.println("[Bat dau] Gui file tu client: outputStream.size(); "
+ outputStream.size());
System.out.println("[Bat dau] Gui file tu client: data.length " + data.length);
DatagramPacket sendPacket = new DatagramPacket(data, data.length,
IPAddress, 9876);
socket.send(sendPacket);
Thread.sleep(1000);
}
System.out.println("[XONG] Gui file tu client");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(outputStream);
event = end();
os.writeObject(event);
byte[] data = outputStream.toByteArray();
DatagramPacket sendPacket = new DatagramPacket(data, data.length,
IPAddress, 9876);
socket.send(sendPacket);
Thread.sleep(1000);
DatagramPacket incomingPacket = new DatagramPacket(incomingData,
incomingData.length);
socket.receive(incomingPacket);
String response = new String(incomingPacket.getData());
System.out.println("phan hoi tu server:" + response);
Thread.sleep(4000);
System.exit(0);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
9
ĐA CS Ngành Mạng
}
public FileEvent end(){
String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("\\") + 1,
sourceFilePath.length());
FileEvent fileEvent = new FileEvent();
fileEvent.setStatus("end");
fileEvent.setDestinationDirectory(destinationPath);
fileEvent.setSourceDirectory(sourceFilePath);
fileEvent.clearFileData();
fileEvent.setFilename(fileName + "_part");
fileEvent.setFileSize(part_number);//luu tong so file truyen di
return fileEvent;
}
public FileEvent getFileEvent() {
FileEvent fileEvent = new FileEvent();
//String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/") + 1,
sourceFilePath.length());
String fileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("\\") + 1,
sourceFilePath.length());
File file = new File(sourceFilePath);
byte[] fileBytes = new byte[MAX_BUFFER_SIZE];
int len;
int filelength = (int) file.length();;
if (file.isFile()) {
try {
FileInputStream fiSteam = new FileInputStream(file);
fiSteam.skip(offset); // skip offset of read byte
DataInputStream diStream = new DataInputStream(fiSteam);
/*check size of the file*/
if(filelength < MAX_BUFFER_SIZE ) //file is small
{
diStream.read(fileBytes);
finish = true;
len = filelength;
fileEvent.setFilename(fileName);
}
else
// file is larger than maximun transport datagram, need to split
{
if(filelength > offset + MAX_BUFFER_SIZE)
{
len = diStream.read(fileBytes,0, MAX_BUFFER_SIZE);
//store at begin of filebyte (offset = 0)
}
else // read the last part
{
len = diStream.read(fileBytes, 0, filelength (int)offset);
//store at begin of filebyte (offset = 0)
}
offset += len;
System.out.println("[READ] read total " + offset);
part_number ++;
if(offset >= filelength) // read the last part
{
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
10
ĐA CS Ngành Mạng
finish = true;
}
}
//closing stream
diStream.close();
fiSteam.close();
//set file event
fileEvent.setDestinationDirectory(destinationPath);
//ten duong
fileEvent.setSourceDirectory(sourceFilePath);
fileEvent.setFileSize(len);
fileEvent.clearFileData();
fileEvent.setFileData(fileBytes);
fileEvent.setFilename(fileName + "_part"+part_number);
fileEvent.setStatus("Success");
// debug
System.out.println("[READ] fileEvent.getFilename : " +
fileEvent.getFilename());
System.out.println("[READ] fileEvent.getDestinationDirectory : " +
fileEvent.getDestinationDirectory());
System.out.println("[READ] fileEvent.getSourceDirectory : " +
fileEvent.getSourceDirectory());
System.out.println("[READ] fileEvent.getFileSize " + fileEvent.getFileSize());
//System.out.println("[READ] FileEvent.getFileData : " +
fileEvent.getFileData());
} catch (Exception e) {
System.out.println("[READ] e.getMessage() : " + e.getMessage());
e.printStackTrace();
fileEvent.setStatus("Error");
}
} else {
System.out.println("duong dan ko chi den 1 file");
fileEvent.setStatus("co loi");
}
return fileEvent;
}
public static void main(String[] args) {
Client client = new Client();
client.setSourceFilePath("D:\\\\FileClient\\\\zshop.png");
client.createConnection();
}
}
1.4.3 Server Java
4.2.1 Gui_Server
package DoAn;
import javax.swing.JOptionPane;
public class GUI_server extends javax.swing.JFrame {
public GUI_server() {
initComponents();
}
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
11
ĐA CS Ngành Mạng
button_khoidong = new javax.swing.JButton();
jButton1 = new javax.swing.JButton();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jTextField1 = new javax.swing.JTextField();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jLabel1.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel1.setText("SERVER");
button_khoidong.setText("Khởi động");
button_khoidong.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
button_khoidongActionPerformed(evt);
}
});
jButton1.setText("exit");
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
jLabel3.setText("lưu");
jTextField1.setText("D:\\FileServer");
jTextField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jTextField1ActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(120, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADI
NG)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(button_khoidong)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jButton1)
.addGap(116, 116, 116))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
layout.createSequentialGroup()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE,
185, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(62, 62, 62))))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADI
NG)
.addGroup(layout.createSequentialGroup()
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
12
ĐA CS Ngành Mạng
.addGap(92, 92, 92)
.addComponent(jLabel3))
.addGroup(layout.createSequentialGroup()
.addGap(140, 140, 140)
.addComponent(jTextField1,
javax.swing.GroupLayout.PREFERRED_SIZE, 239,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)))
.addGap(0, 0, Short.MAX_VALUE))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new
java.awt.Component[] {button_khoidong, jButton1});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(35, 35, 35)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 52,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(22, 22, 22)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASEL
INE)
.addComponent(jLabel3)
.addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
22, Short.MAX_VALUE)
.addComponent(jLabel2)
.addGap(44, 44, 44)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASEL
INE)
.addComponent(button_khoidong)
.addComponent(jButton1))
.addGap(82, 82, 82))
);
pack();
}
private void button_khoidongActionPerformed(java.awt.event.ActionEvent evt) {
Server server = new Server();
server.setFilecoppy(jTextField1.getText());
server.createAndListenSocket();
JOptionPane.showMessageDialog(null, "da nhan thanh cong","Title",
JOptionPane.WARNING_MESSAGE);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
}
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
13
ĐA CS Ngành Mạng
new GUI_server().setVisible(true);
}
});
}
private
private
private
private
private
private
javax.swing.JButton button_khoidong;
javax.swing.JButton jButton1;
javax.swing.JLabel jLabel1;
javax.swing.JLabel jLabel2;
javax.swing.JLabel jLabel3;
javax.swing.JTextField jTextField1;
}
1.4.4
Server.java
package DoAn;
import
import
import
import
import
import
import
import
import
import
import
import
import
static DoAn.Client.MAX_BUFFER_SIZE;
static DoAn.Client.offset;
java.io.*;
java.net.DatagramPacket;
java.net.DatagramSocket;
java.net.InetAddress;
java.net.SocketException;
java.nio.file.Files;
java.nio.file.Path;
java.nio.file.Paths;
java.nio.file.StandardOpenOption;
static java.nio.file.StandardOpenOption.APPEND;
static jdk.nashorn.internal.objects.NativeString.substring;
public class Server {
static int stt;
private DatagramSocket socket = null;
private FileEvent fileEvent = null;
private String filecoppy;
public void setFilecoppy(String filecoppy) {
this.filecoppy = filecoppy;
}
public Server() {
}
public void createAndListenSocket() {
try {
socket = new DatagramSocket(9876);
byte[] incomingData = new byte[1024 * 1000 * 50];
while (true) {
DatagramPacket incomingPacket = new DatagramPacket(incomingData,
incomingData.length);
socket.receive(incomingPacket);
byte[] data = incomingPacket.getData();
ByteArrayInputStream in = new ByteArrayInputStream(data);
ObjectInputStream is = new ObjectInputStream(in);
fileEvent = (FileEvent) is.readObject();
if ( fileEvent.getStatus().equalsIgnoreCase("end")){
addfile();
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
14
ĐA CS Ngành Mạng
System.out.println("ADD FILE");
InetAddress IPAddress = incomingPacket.getAddress();
int port = incomingPacket.getPort();
String reply = "Thank you for the message";
byte[] replyBytea = reply.getBytes();
DatagramPacket replyPacket =
new DatagramPacket(replyBytea, replyBytea.length, IPAddress, port);
socket.send(replyPacket);
break;
}
else if (fileEvent.getStatus().equalsIgnoreCase("Error")) {
System.out.println("Some issue happened while packing the data @ client
side");
System.exit(0);
}
else
{
createAndWriteFile(); // writing the file to hard disk
}
Thread.sleep(1000);
//System.exit(0);
}
} catch (SocketException e) {
System.out.println("ERROR CODE
e.printStackTrace();
} catch (IOException e) {
System.out.println("ERROR CODE
e.printStackTrace();
} catch (ClassNotFoundException e)
System.out.println("ERROR CODE
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("ERROR CODE
e.printStackTrace();
}
01:" + e.getMessage());
02:" + e.getMessage());
{
03:" + e.getMessage());
04:" + e.getMessage());
}
public void addfile() throws IOException{
String fileName = fileEvent.getFilename();//lay phan dau cua ten file
int tongfile=(int)fileEvent.getFileSize();//lay tong se file
String outputFile = fileEvent.getDestinationDirectory();
filecoppy=filecoppy+"\\coppy_"+fileName.substring(0,fileName.length()-5);
File file = new File(filecoppy);
if (file.exists()) file.delete();
file.createNewFile();
Path path = Paths.get(filecoppy);
for(int i=1;i<=tongfile;i++){
String name=outputFile+"\\"+fileName+i;
File namefile = new File(name);
int dai=(int) namefile.length();//do dai cua file noi
byte[] fileBytes = new byte[dai];
FileInputStream fiSteam = new FileInputStream(namefile);
DataInputStream diStream = new DataInputStream(fiSteam);
int a=diStream.read(fileBytes,0, (int) namefile.length());
System.out.println("so byte doc duoc"+a);
Files.write(path, fileBytes, APPEND);
fiSteam.close();
diStream.close();
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
15
ĐA CS Ngành Mạng
boolean success = (new File (name)).delete();
if (success)
{
System.out.println("The file has been successfully deleted");
}
}
}
public void createAndWriteFile() {
FileWriter fw = null;
String outputFile = fileEvent.getDestinationDirectory() + "\\"+
fileEvent.getFilename();
}
}
if (!new File(fileEvent.getDestinationDirectory()).exists()) {
new File(fileEvent.getDestinationDirectory()).mkdirs();
}
System.out.println(fileEvent.getFilename() + " length " +
fileEvent.getFilename().length());
try {
File dstFile = new File(outputFile);
FileOutputStream fileOutputStream = null;
fileOutputStream = new FileOutputStream(dstFile);
fileOutputStream.write(fileEvent.getFileData(),0,(int)fileEvent.getFileSize());
fileOutputStream.flush();
fileOutputStream.close();
System.out.println("Output file : " + outputFile + " is successfully saved ");
} catch (FileNotFoundException e) {
System.out.println("ERROR CODE 05:" + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.out.println("ERROR CODE 06:" + e.getMessage());
e.printStackTrace();
}
public static void main(String[] args) {
Server server = new Server();
server.createAndListenSocket();
}
1.4.5 FileEvent.java
package DoAn;
import java.io.Serializable;
public class FileEvent implements Serializable {
public FileEvent() {
}
private static final long serialVersionUID = 1L;
private
private
private
private
private
private
String destinationDirectory;
String sourceDirectory;
String filename;
long fileSize;
byte[] fileData;
String status;
public String getDestinationDirectory() {
return destinationDirectory;
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
16
ĐA CS Ngành Mạng
}
}
public void setDestinationDirectory(String destinationDirectory) {
this.destinationDirectory = destinationDirectory;
}
public String getSourceDirectory() {
return sourceDirectory;
}
public void setSourceDirectory(String sourceDirectory) {
this.sourceDirectory = sourceDirectory;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public byte[] getFileData() {
return fileData;
}
public void clearFileData()
{
fileData = null;
}
public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
17
ĐA CS Ngành Mạng
1.5 KẾT LUẬN
1.5.1 Kết quả chạy thực tế
Hình 1: Gui_Server
Hình 2: Gui_Client
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
18
ĐA CS Ngành Mạng
Hình 3: Thông báo kết nối Thành Công
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
19
ĐA CS Ngành Mạng
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
20
ĐA CS Ngành Mạng
Hình 4: Các thông báo truyền file
Hình 5: Kết quả truyền file .3gp và file .png
1.5.2 Kết luận
Chương trình thực hiện được yêu cầu của đề tài là truyền file qua mạng qua
socket sử dụng giao thức UDP.
Hệ thống hoạt động ổn định, Chương trình chạy ổn định.
Giao diện đơn giản, đặc trưng dễ sử dụng.
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
21
ĐA CS Ngành Mạng
1.6 TÀI LIỆU THAM KHẢO
[1] />[2] />[3] />[4] Tài Liệu Lập Trình Mạng của khoa CNTT.
PHẦN 2: ĐỒ ÁN HỆ ĐIỀU HÀNH
2.1 GIỚI THIỆU
Đề Tài: Xây dựng chương trình nhận bắt bàn phím, sử dụng kĩ thuật
Hook trong Windows.
Xây dựng chương trình nhận bắt bàn phím sử dụng kĩ thuật Hook trong
Windows. Vận dụng kiến kiến về kĩ thuật hook WH_KEYBOARD_LL để xây dựng
chương trình bằng ngôn ngữ C++. Chương trình chạy không giao diện nhằm ghi lại
bàn phím để khi được cài vào trong máy.
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
22
ĐA CS Ngành Mạng
2.2 CƠ SỞ LÍ THUYẾT
2.2.1
Tổng quan Hook trong Windows
Hook là một cơ chế mà một ứng dụng có thể chặn các sự kiện, như các thông
điệp, thao tác chuột, bàn phím. Hàm dùng để chặn một loại sự kiện riêng biệt được
gọi là hook procedure/ Hook function. Mỗi khi nhận được sự kiện, hook proceduce
có thể thay đổi và thậm chí hủy bỏ các sự kiện đó.
Có nhiều loại hook (như chuột, bàn phím) và hệ điều hành luôn duy trì một
danh sách các hook procedure cho mỗi loại đó. Mỗi danh sách các Hook procedure
này được gọi là hook chain. Bản chất của hook chain là một dãy các con trỏ hàm
trỏ đến các Hook procedure. nhiều loại hook (như chuột, bàn phím) và hệ điều hành
luôn duy trì một danh sách các hook procedure cho mỗi loại đó. Mỗi danh sách các
Hook procedure này được gọi là hook chain. Bản chất của hook chain là một dãy
các con trỏ hàm trỏ đến các Hook procedure.
2.2.2
Chức năng của Hook
- Bắt và giả lập các thông điệp bàn phím, chuột
- Cung cấp chức năng Help (F1) cho ứng dụng
C++, một ngôn ngữ lập trình hướng đối tượng quá nổi tiếng được nâng cấp từ
ngôn ngữ C trước đó. C++ mạnh mẽ và linh động, thích hợp để viết các chương
trình yêu cầu tốc độ xử lí cao hoặc giao tiếp phần cứng. Như vậy việc tương tác với
hệ điều hành, mà ở phạm vi đề tài là truy cập các tệp tin trên đĩa thì C++ rất thích
hợp.
DLL (Dynamic Link Library) là một thư viện liên kết động. File DLL chứa
những chỉ lệnh mà các chương trình khác có thể gọi đến để làm một tác vụ nào đó.
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
23
ĐA CS Ngành Mạng
Về cơ bản, DLL cũng giống như EXE, tuy nhiên các file này được đặt tên khác
nhau trong quá trình liên kết. Sử dụng DLL sẽ tiết kiệm bộ nhớ khi chương trình trở
nên lớn và phức tạp, tăng tính sử dụng lại và đặc biệt là tạo ra khả năng tương tác
giữa các ngôn ngữ lập trình khác nhau.
2.2.3 Lý thuyết về WH_KEYBOARD_LL
1. Chương trình cần dùng các hàm
SetwindowHookEx và UnHookWindowHookEx
2. Hook cục bộ (Thread hook) phân loại theo phạm vi.
hàm giám sát được cài đặt sau thông điệp ứng dụng chỉ kiểm soát tiến trình
trong một ứng dụng cụ thể nào đó được xác định lúc cài đặt
3. Hook toàn cục
Hàm giám sát được cài đặt sau hàng đợi của thông điệp hệ thống, kiểm soát toàn
bộ tiến trình trong hệ thống.
4. Phân loại theo thông điệp ( loai Hook và công dụng) ở đây ta tập trung vào
loại hook ( WH_kEYBOARD_LL và WH_KEYBOARD).
WH_KEYBOARD_LL: Cho phép giám sát sự kiện của bàn phím tới hàng đợt
ứng dụng
WH_KEYBOARD: Giám sát thông điệp từ bàn phím WM_KEYDOWN,
WH_KEYUP.
5. Thủ tục được gọi bởi hệ điều hành gọi là CallBack
PHÂN TÍCH VÀ THIẾT KẾ GIẢI THUẬT
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
24
ĐA CS Ngành Mạng
1.6.1 Sơ đồ hoạt động của hệ thống
Sơ đồ hoạt động tổng quát của hệ thống
1.6.2 Giải thuật xây dựng các bước
Bước 1: tạo file DLL chứa hàm lọc. Mọi hàm lọc đều có dạng như sau:
LRESULT CALLBACK (int nCode, WPARAM wParam, LPARAM lParam)Bên trong hàm
lọc chúng ta có thể tùy ý làm đủ chuyện trời đất. Tuy nhiên, phải tuân thủ theo
một số nguyên tắt sau:
- Nếu nCode < 0 thì không được làm gì mà phải gọi ngay hàm CallNextHookE) (sẽ
trình bày sau) và trả về giá trị... return bởi nó.
- Nếu có xử lý ít nhiều thì hàm lọc phải trả về giá trị khác 0
Bước 2: tạo chương trình cài đặt Hook. Chương trình này sử dụng 3 hàm API sau
đây để “móc” hàm lọc vào các sự kiện:
a) Hàm cài đặt một hàm lọc
HHOOK SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod,
DWORD dwThreadId)Các tham số có ý nghĩa như sau:
+ idHook: xác định loại hook mà ta muốn cài đặt (ví dụ: WH_KEYBOARD,
WH_MSGFILTER…)
+ lpfn : địa chỉ hàm lọc mà ta muốn gắn với hook
+ hMod : handle của module chứa hàm lọc (là handle của file DLL trong trường
hợp Hook toàn cục)
+ dwThreadID : định danh của thread ứng với hook đang được cài đặt (nếu = 0 thì
Hook có phạm vi toàn hệ thống và bao hảm cả mọi thread đang tồn tại)
b) Hàm gỡ bỏ một hàm lọc
BOOL UnhookWindowsHookEx(HHOOK hHook)Tham số:
+ hHook: handle của hook cần gỡ bỏ (chính là giá trị được trả vể bởi hàm
SetWindowsHookEx khi cài đặt)
SVTH: NGUYỄN ĐÌNH PHÁT – LỚP 13T3 NHÓM 10
25