Chương 1 CƠ SỞ LÝ THUYẾT VỀ .NET 4
1.1 Giới thiệu về ngôn ngữ C#: 4
1.2 Kiến trúc .Net 6
1.3 Ngôn ngữ C# 8
Chương 2 LẬP TRÌNH MẠNG TRONG .NET FRAMEWORK 9
2.1 Sử dụng các lớp hỗ trợ được xây dựng từ lớp Socket 9
2.1.1 Lớp TCPClient 9
2.1.2 Lớp TCPListener 10
2.1.3 Lớp UDPClient 11
2.2 Socket không đồng bộ 13
2.2.1 Mô hình xử lý sự kiện của Windows 13
2.2.2 Sử dụng Socket không đồng bộ 13
2.3 Sử dụng Thread trong các ứng dụng mạng 17
2.3.1 Một số khái niệm 17
2.3.2 Sử dụng Thread trong chương trình .Net 17
2.3.3 Sử dụng Threadpool trong các chương trình .Net 19
Chương 3 CHƯƠNG TRÌNH REMOTE DESKTOP 20
3.1 Giới thiệu giao thức Remote Desktop: 20
3.2 Cơ chế hoạt động của Remote Desktop: 21
3.2.1 Connection Initiation 21
3.2.2 Basic Settings Exchange 21
3.2.3 Channel Connection 22
3.2.4 RDP Sercurity Commencement 23
3.2.5 Secure Settings Exchange: 23
3.2.6 Licensing: 23
3.2.7 Capabilities Negotiation: 24
3.2.8 Connection Finalization: 24
3.3 Chương trình: 25
3.3.1 Yêu cầu bài toán: 25
3.3.2 Giao diện chương trình: 25
3.3.3 Code chương trình Server: 27
3.3.4 Code chương trinh client: 35
3.4 Hướng dẫn sử dụng 44
3.4.1 Khởi động chương trình 44
3.4.2 Gửi và nhận file 45
3.4.3 Điều khiển máy từ xa. 46
3.4.4 Thực thi một ứng dụng 46
KÊT LUẬN 47
TÀI LIỆU THAM KHẢO 48
48 trang |
Chia sẻ: netpro | Lượt xem: 5083 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Đề tài Xây dựng chương trình Remote Desktop, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
này thường sử dụng những cửa sổ, menu, toolbar, button hay các thành phần GUI khác, và chúng thường truy cập các tài nguyên cục bộ như là các tập tin hệ thống, các thiết bị ngoại vi như máy in.
Một loại ứng dụng client khác với ứng dụng truyền thống như trên là ActiveX control (hiện nay nó được thay thế bởi các Windows Form control) được nhúng vào các trang web trên Internet. Các ứng dụng này cũng giống như những ứng dụng client khác là có thể truy cập tài nguyên cục bộ.
Những lớp .NET Framework chứa trong .NET Framework được thiết kế cho việc sử dụng phát triển các GUI. Điều này cho phép người phát triển nhanh chóng và dễ dàng tạo các cửa sổ, button, menu, toolbar, và các thành phần khác trong các ứng dụng được viết phục vụ cho lĩnh vực thương mại.
1.3. Ngôn ngữ C#
Ngôn ngữ C# khá đơn giản, chỉ khoảng 80 từ khóa và hơn mười mấy kiểu dữ liệu được xây dựng sẵn. Tuy nhiên, ngôn ngữ C# có ý nghĩa cao khi nó thực thi những khái niệm lập trình hiện đại. C# bao gồm tất cả những hỗ trợ cho cấu trúc, thành phần component, lập trình hướng đối tượng.
Phần cốt lõi hay còn gọi là trái tim của bất cứ ngôn ngữ lập trình hướng đối tượng là sự hỗ trợ của nó cho việc định nghĩa và làm việc với những lớp. Những lớp thì định nghĩa những kiểu dữ liệu mới, cho phép người phát triển mở rộng ngôn ngữ để tạo mô hình tốt hơn để giải quyết vấn đề. Ngôn ngữ C# chứa những từ khóa cho việc khai báo những kiểu lớp đối tượng mới và những phương thức hay thuộc tính của lớp, và cho việc thực thi đóng gói, kế thừa, và đa hình, ba thuộc tính cơ bản của bất cứ ngôn ngữ lập trình hướng đối tượng.
Trong ngôn ngữ C# mọi thứ liên quan đến khai báo lớp điều được tìm thấy trong phần khai báo của nó. Định nghĩa một lớp trong ngôn ngữ C# không đoi hỏi phải chia ra tập tin header và tập tin nguồn giống như trong ngôn ngữ C++. Hơn thế nữa, ngôn ngữ C# hỗ trợ kiểu XML, cho phép chèn các tag XML để phát sinh tự động các document cho lớp.
Ngôn ngữ C# cung cấp những đặc tính hướng thành phần (component-oriented), như là những thuộc tính, những sự kiện. Lập trình hướng thành phần được hỗ trợ bởi CLR cho phép lưu trữ metadata với mã nguồn cho một lớp.
CHƯƠNG 2 : LẬP TRÌNH MẠNG TRONG .NET FRAMEWORK
2.1 Sử dụng các lớp hỗ trợ được xây dựng từ lớp Socket
2.1.1 Lớp TCPClient
Dùng giao thức này thì hai bên không cần phải thiết lập kết nối trước khi gửi do vậy mức dộ tin cậy ko cao. Để đảm bảo độ tin cậy trong các ứng dụng mạng người ta còn sử dụng một giao thức khác gọi là giao thức có kết nối: TCP (transport control protocol). Để lập trình theo giao thức TCP, MS.NET cung cấp hai lớp có tên là TCPClient và TCPListener.
Các thành phần của lớp TcpClient
Phương thức khởi tạo:
Constructor method
Name
Description
TcpClient ()
Tạo một đối tượng TcpClient. Chưa đặt thông số gì.
TcpClient (IPEndPoint)
Tạo một TcpClient và gắn cho nó một EndPoint cục bộ. (gán địa chỉ máy cục bộ và số hiệu cổng để sử dụng trao đổi thông tin về sau)
TcpClient (RemoteHost: String Int32)
Tạo một đối tượng TcpClient và kết nối đến một máy có địa chỉ và số hiệu cổng được truyền vào. RemoteHost có thể là địa chỉ IP chuẩn hoặc tên máy.
Một số thuộc tính:
Name
Description
Available
Cho biết số byte đã nhận về từ mạng và có sẵn để đọc
Client
Trả về socket ứng với TCPClient hiện hành
Connected
Trạng thái cho biết đã kết nối được đến server hay chưa ?
Một số phương thức:
Name
Description
Close
Giải phóng đối tượng TcpClient nhưng không đóng kết nối
Connect (RemoteHost, Port)
Kết nối đến một máy TCP khác có tên và số hiệu cổng
GetStream
Trả về NetworkStream để từ đó giúp ta gửi hay nhận dữ liệu. (thường làm tham số khi tạo StreamReader và StreamWriter).
Khi đã gắn vào StreamReader vá StreamWriter rồi thì ta có thể gửi và nhận dữ liệu thông qua các phương thức Readln, writeline tương ứng của các lớp này.
2.1.2. Lớp TCPListener
TCPListener là một lớp cho phép người lập trình có thể xây dựng các ứng dụng server.
Các thành phần của lớp TcpListent:
Phương thức khởi tạo:
Constructor method
Name
Description
TcpListener (Port: Int32)
Tạo một TcpListener và lắng nghe tại cổng chỉ định
TcpListener (IPAddress, Int32)
Tạo một TcpListener và lắng nghe các kết nối đến tại địa chỉ IP và cổng chỉ định
TcpListener (IPEndPoint)
Tạo một TcpListener với giá trị EndPoint truyền vào.
Các phương thức khác:
Name
Description
AcceptTcpClient
Chấp nhận một yêu cầu kết nối đang chờ. (ứng dụng sẽ dừng tại câu lệnh này cho đến khi nào có một kết nối đến)
AcceptSocket
Chấp nhận một yêu cầu kết nối đang chờ.
Pending
Cho biết liệu có kết nối nào đang chờ đợi không? ( True = có).
Start
Bắt đầu lắng nghe các yêu cầu kết nối
Stop
Dừng việc nghe.
2.1.3. Lớp UDPClient
Giao thức UDP (user datagram protocol hay user define protocol) là một giao thức phi kết nối có nghĩa là một bên có thể gửi dữ liệu cho bên kia mà không cần biết là bên đó có sẵn sàng hay chưa? Giao thức này không tin cậy bằng giao thức TCP nhưng tốc độ của nó nhanh và dễ cài đặt. ngoài ra, với giao thức UDP ta còn có thể gửi được gói tin quảng bá đến nhiều máy.
Trong .NET, lớp UDPClient đóng gói các chức năng của giao thức UDP.
Constructor method
Description
UdpClient ()
Tạo một đối tượng (thể hiện) mới của lớp UDPClient.
UdpClient (AddressFamily)
Tạo một đối tượng mới của lớp UDPClient. Thuộc một dòng địa chỉ được chỉ định.
UdpClient (Int32)
Tạo một UdpClient và gắn một cổng cho nó
UdpClient (IPEndPoint)
Tạo một UdpClient và gắn một IPEndPoint cho nó
UdpClient (Int32, AddressFamily)
Tạo một UdpClient và gắn số hiệu cổng, AddressFamily
UdpClient (String, Int32)
Tạo một UdpClient và thiết lập với một máy trạm từ xa mặc định.
PUBLIC Method
Name
Description
BeginReceive
Nhận dữ liệu không đồng bộ từ máy tính từ xa.
BeginSend
Gửi không đồng bộ dữ liệu tới máy ở xa
Close
Đóng kết nối
Connect
Thiết lập một default remote host.
EndReceive
Kết thúc nhận dữ liệu không đồng bộ ở trên
EndSend
Kết thúc việc gửi dữ liệu không đồng bộ ở trên
Receive
Nhận dữ liệu (đồng bộ) do máy tính ở xa gửi
Send
Gửi dữ liệu (đồng bộ) cho máy ở xa.
2.2. Socket không đồng bộ
2.2.1. Mô hình xử lý sự kiện của Windows
Mô hình sử lý sự kiện được thể hiện qua mô hình sau:
Thông qua mô hình này ta có thể ủy nhiệm cho môt thủ tục nào đó thực hiện khi sự kiện sảy ra trên Control.
2.2.2. Sử dụng Socket không đồng bộ
Để lập trình không đồng bộ với Socket chúng ta sử dụng các phương thức cho việc sử dụng bất đồng bộ.
Các phương thức cho việc lập trình bất đồng được chia làm 2 bắt đầu bằng Begin và End:
Phương thức bắt đầu bằng Begin, bắt đầu một chức năng và được đăng ký với phương thức AsyncCallback.
Bắt đầu bằng End chỉ chức năng hoàn thành khi AsyncCallback đươc gọi
Requests Started By …
Description of Request
Requests Ended BY …
BeginAccept ()
To accept an incoming connection
EndAccept ()
BeginConnect ()
To connect to a remote host
EndConnect ()
BeginReceive ()
To retrieve data from a socket
EndReceive ()
BeginReceiveFrom ()
To retrieve data from a specific remote host
EndReciveFrom()
BeginSend ()
To send data from a socket
EndSend ()
BeginSendTo ()
To send data to a specific remote host
EndSendTo ()
Để chấp nhận kết nối bất đồng bộ ta sử dụng phương thức BeginAccept() và EndAccept() như sau:
Phương thức BeginAccept() và EndAccept()
IAsyncResult BeginAccept(AsyncCallback callback, object state)
Socket EndAccept(IAsyncResult iar);
Để thiết lập phương thức kết nối theo cách bất đồng bộ ta sử dụng phương thức BeginConnect() và EndConnect() như sau:
Phương thức BeginConnect() và EndConnect()
Socket newsock = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep =new IPEndPoint(IPAddress.Parse("127.0.0.1"), 9050);
newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
Trong đó phương thức Connected thường được viết như sau:
public static void Connected(IAsyncResult iar) {
Socket sock = (Socket)iar.AsyncState;
try {
sock.EndConnect(iar);
} catch (SocketException) {
Console.WriteLine("Unable to connect to host");
}
}
Để gửi dữ liệu bất đồng bộ chúng ta làm như sau:
Phương thức BeginSend() và EndSend()
BeginSend()
IAsyncResult BeginSend(byte[] buffer, int offset, int size, SocketFlags sockflag, AsyncCallback callback, object state)
EndSend()
int EndSend(IAsyncResult iar)
Trong đó phương thức SendData thường được viết như sau:
private static void SendData(IAsyncResult iar) {
Socket server = (Socket)iar.AsyncState;
int sent = server.EndSend(iar);
}
Tương tự như giao thức hướng kết nối nếu ta sử dụng gửi dữ liệu theo giao thức không hướng kết nối chúng ta cũng thực hiện tương tự như sau:
Phương thức BeginSendTo() và EndSendTo()
IAsyncResult BeginSendTo(byte[] buffer,int offset,int size,SocketFlags sockflag, EndPoint ep, AsyncCallback callback, object state)
Để nhận dữ liệu bất đồng bộ ta thực hiện như sau:
Nhận dữ liêu với giao thức hướng kết nối:
Phương thức BeginRecieve và EndRecive()
sock.BeginReceive(data, 0, data.Length, SocketFlags.None, new
AsyncCallback(ReceivedData), sock);
Với ReceivedData được định nghĩa như sau:
void ReceivedData(IAsyncResult iar) {
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
string receivedData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(receivedData);
}
Nhận dữ liệu bất đồng bộ với giao thức không hướng kết nối
Phương thức BeginReceiveFrom() và EndReceiveFrom()
sock.BeginReceive(data,0,data.Length,SocketFlags.None,refiep,new AsyncCallback (ReceiveData) , sock);
void ReceiveData(IasyncResult iar){
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceiveFrom(iar);
string stringData = Encoding.ASCII.GetString(data, 0,
recv);
Console.WriteLine(stringData);
}
2.3. Sử dụng Thread trong các ứng dụng mạng
2.3.1. Một số khái niệm
Đa nhiệm (multitasking ): là khả năng hệ điều hành làm nhiều công việc tại một thời điểm.
Tiến trình (Process): khi chạy một ứng dụng hệ điều hành sẽ cấp phát riêng cho ứng dụng đó bộ nhớ và các tài nguyên khác. Bộ nhớ và tài nguyên vật lý riêng biệt này được gọi là một tiến trình. Các tài nguyên và bộ nhớ của một tiến trình thì chỉ tiến trình đó được phép truy cập.
Tuyến (Thread ): trong hệ thống một tiến trình có thể có một hoặc nhiều chuỗi thực hiện tách biệt khác nhau và có thể chạy đồng thời. mỗi chuỗi thực hiện này được gọi là 1 tuyến (Thread). Trong 1 ứng dụng Thread khởi tạo đầu tiên gọi là Thread sơ cấp hay Thread chính.
2.3.2. Sử dụng Thread trong chương trình .Net
Để sử dụng Thread trong .NET ta sử dụng namespace System.Threading
Một số phương thức thường dùng:
Public Method
Name
Mô tả
Abort ()
Kết thúc Thread
Join ()
Buộc chương trình phải chờ cho thread kết thúc (Block) thì mới thực hiện tiếp (các câu lệnh đứng sau Join).
Resume ()
Tiếp tục chạy thread đã tạm ngừng – suspended
Sleep ()
Static method: tạm dừng thread trong một khoảng thời gian.
Start ()
Bắt đầu chạy (khởi động) một thread. Sau khi gọi phương thức này, trạng thái của thread chuyển từ trạng thái hiện hành sang Running.
Suspend ()
Tạm ngưng thread. (phương thức này được loại khỏi phiên bản VS.NET 2005)
Một số thuộc tính thường dùng:
Public Property
Name
Mô tả
CurrentThread
This static property: trả về thread hiện hành đang chạy.
IsAlive
Trả về giá trị cho biết trạng thái thực thi của thread hiện hành.
IsBackground
Sets or gets giá trị cho biết là thread là background hay foreground thread.
IsThreadPoolThread
Gets a value indicating whether a thread is part of a thread pool.
Priority
Sets or gets giá trị để chỉ định độ ưu tiên ( dành nhiều hay ít CPU cho thread). Cao nhất là 4, thấp nhất là 0.
ThreadState
Lấy về trạng thái của thread (đang dừng, hay đang chạy…)
Tạo một tuyến trong C#
……
Thread newThread=newThread(new ThreadStart(newMethod));
…….
}
void newMethod() {
. . .
}
2.3.3. Sử dụng Threadpool trong các chương trình .Net
Method
Description (Mô tả)
BindHandle ()
Binds an operating system handle to the thread pool
GetAvailableThreads()
Gets the number of worker threads available for use in the thread pool
GetMaxThreads ()
Gets the maximum number of worker threads available in the thread pool
QueueUserWorkItem ()
Queues a user delegate waiting for a WaitHandle object
UnsafeQueueUserWorkItem ()
Queues an unsafe user delegate to the thread pool but does not propagate the calling stack onto the worker thread
UnsafeRegisterWaitForSingleObject ()
Registers an unsafe delegate waiting for a WaitHandle object
CHƯƠNG 3: CHƯƠNG TRÌNH REMOTE DESKTOP
3.1. iới thiệu giao thức Remote Desktop:
Giao thức Remote Desktop là kết nối cơ bản với giao diện đồ họa được thiết kế để tạo điều kiện thuận lợi cho người sử dụng tương tác với một hệ máy tính từ xa bằng cách cập nhật những thông tin đồ họa đến từ máy tính từ xa tới người sử dụng và đồng bộ thông tin quản lý của người dùng tương tác đến máy tính ở xa, giống như đang ngồi tại chính máy đó.
Giao thức này cũng cung cấp một cơ chế cho phép đơn giản hóa việc truyền thông chuyên dụng mở rộng giữa người sử dụng máy tính trực tiếp và những thành phần chạy trên máy tính ở .
3.2. cơ chế hoạt động của Remote Desktop:
3.2.1. Connection Initiation
Client thực hiện kết nối đến server bằng cách gửi gói tin yêu cầu kết nối PDU x.224. Server phản hồi lại với gói xác nhận kết nối x.224. Từ điểm này tất cả các dữ liệu giữa client và server sẽ được bao bọc trong gói x.224 PDU.
3.2.2. Basic Settings Exchange
sự trao đổi cấu hình giữa client và server được thực hiện thông qua việc sử dụng kết nối ban đầu MCS (MCS connect Initial) và gói phúc đáp MCS PDUs (MCS Connect Reponse.) Một kết nối PDU ban đầu chứa yêu cầu kết nối thời gian thực GCC (GCC Conference Create Request), trong khi một kết nối phúc đáp PDU chứa một phúc đáp kết nối GCC (GCC Conference
Create Response). Hai gói Điều khiển Hội nghị Chung “Generic Conference Control” (GCC) này chứa đựng ghép nối những khối cấu hình cài đặt
dữ liệu (dữ liệu lõi, dữ liệu bảo mật và dữ liệu mạng…) nào được đọc bởi client và Server.
3.2.3. Channel Connection
Client gửi một MCS Erect Domain Request PDU, tiếp theo là một MCS
Attach User Request PDU đính kèm danh tính người dùng chính với miền. Server phúc đáp bằng MCS Attach User Response PDU với id kênh người phục vụ. client sẽ tiến hành kết nối vào kênh người sử dụng, kênh nhập/xuất (I/O) và tất cả các kênh ảo (kênh nhập/xuất, IDs kênh ảo cố định tồn tại từ dữ liệu nhúng trong gói GCC) và sử dụng tập hợp MCS Channel Join Request PDUs. Server xác nhận lại mỗi kênh với MCS Channel Confirm PDU. (Client chỉ gửi gói Channel Join Request sau khi đã nhận Channel Join Confirm PDU từ yêu cầu gửi trước đó.)
Từ điểm này, tất cả dữ liệu được gửi kế tiếp từ client đến server đều được đóng gói trong MCS Send Data Request PDU, trong khi dữ liệu gửi đi từ server đến client được đóng gói trong MCS Send Data Indication PDU. Đây là dữ liệu được đóng gói bởi Dữ liệu X.224 PDU.
3.2.4. RDP Sercurity Commencement
Nếu phương pháp tiêu chuẩn bảo mật RDP đang được sử dụng và mã hóa có hiệu lực (điều này được xác định bằng cách kiểm tra các dữ liệu nhúng trong GCC Conference
Create Response packet) sau đó client gửi một Security Exchange PDU có chứa một mật mã 32-byte ngẫu nhiên số đến Server. Con số này ngẫu nhiên được mã hóa với khóa công khai của máy chủ (khóa công khai của máy chủ, cũng như tạo ra một máy chủ 32-byte số ngẫu nhiên, được cả hai thu được từ các dữ liệu nhúng trong Hội nghị GCC gói Tạo đáp ứng). Các client và server sau đó sử dụng hai 32-byte số ngẫu nhiên để tạo ra các phím phiên sử dụng để mã hóa và xác nhận tính toàn vẹn của lưu lượng RDP tiếp theo.
Từ điểm này, tất cả lưu lượng RDP tiếp theo có thể được mã hóa và một tiêu đề an ninh được bao gồm với các dữ liệu nếu mã hóa có hiệu lực (các Thông tin khách hàng và PDUs cấp Giấy phép có một ngoại lệ trong họ luôn luôn có một tiêu đề an ninh). Các Header Security sau các X.224 và MCS Headers và cho biết dù dữ liệu đính kèm được mã hóa. Ngay cả khi mã hóa có hiệu lực máy chủ đến lưu lượng khách hàng có thể không phải luôn luôn được mã hóa, trong khi khách hàng đến máy chủ lưu lượng truy cập sẽ luôn luôn được mã hóa bởi Microsoft RDP triển khai (mã hóa của PDUs cấp phép là tùy chọn).
3.2.5. Secure Settings Exchange:
(Sự Trao đổi những thiết đặt An toàn): An toàn dữ liệu máy client (như là username, mật khẩu, auto-reconnect cookie) là gửi đến server sử dụng Client Info PDU.
3.2.6. Licensing:
Mục đích của việc trao đổi cấp phép để đồng bộ chung một giấy phép từ server đến client. Client cần lưu trữ giấy phép này và thông qua những kết nối đó gửi giấy phép đến server xác thực.Tuy nhiên, trong một só trường hợp client không được cấp giấy phép đến nơi lưu trữ. Trên thực tế, những gói được trao đổi trong thời gian pha này của giao thức phụ thuộc cơ chế cấp phép từ server.
3.2.7. Capabilities Negotiation:
Server gửi tập hợp những khả năng mà nó hỗ trợ đến client trong một Demand Active PDU. Client trả lời với những khả năng có thể bằng cách gửi gói Confirm Active PDU.
3.2.8. Connection Finalization:
Client và server gửi PDUs xuyên suốt quá trình kết nối. PDUs từ client tới người server và từ server tới client được trao đổi trong suốt pha có thể.
Sau khi client nhận Font Map PDU nó có thể bắt đầu điều khiển chuột và phím đến server, nó tiến hành tương tác với Remote computer với giao diện đồ họa.
3.3. Chương trình:
3.3.1. Yêu cầu bài toán:
Dựa trên nên tảng giao thức Remote Desktop có sẵn, tiến hành xây dựng mô hình Client-Server hỗ trợ các tính năng cơ bản tương tác với máy tính từ xa như tắt máy, khởi động lại máy, ngủ đông, khóa máy, chạy một số ứng dụng, gửi thông điệp, gửi một file hay lấy 1 file từ máy đang điều khiển… sử dụng ngôn ngữ lập trình C#.
3.3.2. Giao diện chương trình:
Server:
Client:
3.3.3. Code chương trình Server:
Lắng nghe kết nối trên port 8080
private void Main_Load(object sender, EventArgs e)
{
langnghe = new Thread(new ThreadStart(LangNghe));
langnghe.Start();
tinhtrang.Text = "Tình trạng: Đang lắng nghe qua cổng 8080...";
label1.Text = "Địa chỉ máy chủ: " + Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
}
public void LangNghe()
{
nghea = new TcpListener(8080);
nghea.Start();
try
{
client = nghea.AcceptTcpClient();
}
catch (Exception)
{
nghea.Stop();
}
thdHandler = new Thread(new ThreadStart(NhanDuLieu));
thdHandler.Start();
}
Nhận dữ liệu và các lệnh từ client
public void NhanDuLieu()
{
try
{
NetworkStream stream = new NetworkStream(client.Client);
byte[] data = new byte[1024];
int receiv = 0;
String Stringdata;
while (true)
{
receiv = client.Client.Receive(data);
Stringdata = Encoding.UTF8.GetString(data, 0, receiv).TrimEnd();
String[] s = Stringdata.Split('$');
if (s[0] == commandType.NgatKetNoi.ToString())
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.NgatKetNoi.ToString()));
nghea.Stop();
client.Close();
Application.Restart();
break;
}
if (s[0] == commandType.Thoat.ToString())
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.NgatKetNoi.ToString()));
nghea.Stop();
client.Close();
Application.Exit();
break;
}
else if (s[0] == commandType.KetNoi.ToString())
{
ip = s[1];
tinhtrang.Text = "Tình trạng: Đã kết nối đến " + ip;
}
else if (s[0] == commandType.Chat.ToString())
{
MessageBox.Show(s[1], ip);
}
else if (s[0] == commandType.File.ToString())
{
FileStream f1 = null;
BinaryWriter f2 = null;
try
{
f1 = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + s[2], FileMode.Create);
f2 = new BinaryWriter(f1);
int block = 1024;
byte[] buff = new byte[block];
long seek = 0;
long max = long.Parse(s[1]);
do
{
receiv = client.Client.Receive(buff);
f2.Write(buff);
seek++;
}
while (seek < max);
}
catch (Exception ioe)
{
MessageBox.Show("Lỗi: " + ioe.Message, "Loi!");
}
finally
{
if (f2 != null) f2.Close();
if (f1 != null) f1.Close();
}
}
else if (s[0] == commandType.LayFile.ToString())
{
FileInfo f = new FileInfo(s[1]);
if (!f.Exists)
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.Chat.ToString() + "$" + "Không tồn tại: " + s[1]));
}
else
{
FileStream f1 = null;
BinaryReader f2 = null;
try
{
f1 = new FileStream(s[1], FileMode.Open);
f2 = new BinaryReader(f1);
int block = 1024;
byte[] buff = new byte[block];
long seek = 0;
long max = f1.Length / block + 1;
client.Client.Send(Encoding.UTF8.GetBytes(commandType.File + "$" + max + "$" + new FileInfo(s[1]).Name));
do
{
BinaryWriter b = new BinaryWriter(client.GetStream());
b.Write(f2.ReadBytes(block));
seek++;
}
while (seek < max);
}
catch (Exception ioe)
{
MessageBox.Show("Lỗi: " + ioe.Message, "Loi!");
}
finally
{
if (f2 != null) f2.Close();
if (f1 != null) f1.Close();
}
}
}
else if (s[0] == commandType.KhoiDongLai.ToString())
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.NgatKetNoi.ToString()));
ExitWindowsEx(2, 0);
}
else if (s[0] == commandType.TatMay.ToString())
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.NgatKetNoi.ToString()));
ExitWindowsEx(1, 0);
}
else if (s[0] == commandType.TamDung.ToString())
{
Application.SetSuspendState(PowerState.Suspend, true, true);
}
else if (s[0] == commandType.KhoaMay.ToString())
{
LockWorkStation();
}
else if (s[0] == commandType.NguDong.ToString())
{
Application.SetSuspendState(PowerState.Hibernate, true, true);
}
else if (s[0] == commandType.ChayUngDung.ToString())
{
try
{
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo(s[1]);
if (s[2] != "") psi.Arguments = s[2];
psi.ErrorDialog = false;
if (bool.Parse(s[3]))
{
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
}
p.StartInfo = psi;
p.Start();
if (bool.Parse(s[3]))
{
StreamReader sr = p.StandardOutput;
string re = sr.ReadToEnd();
client.Client.Send(Encoding.UTF8.GetBytes(commandType.ThongBao.ToString() + "$" + re));
}
else client.Client.Send(Encoding.UTF8.GetBytes(commandType.Chat.ToString() + "$Đã mở: " + s[1]));
p.Close();
}
catch (Exception e)
{
client.Client.Send(Encoding.UTF8.GetBytes(commandType.ThongBao.ToString() + "$Lỗi: " + e.ToString()));
}
}
}
return;
}
catch (Exception err1)
{
MessageBox.Show(err1.Message.ToString(), "Loi!!!");
if (client != null) client.Client.Close();
}
}
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
3.3.4. Code chương trinh client:
Kết nối đến client thông qua địa chỉ ip và port
private void Main_Load(object sender, EventArgs e)
{
ip = Dns.GetHostByName(Dns.GetHostName()).AddressList[0].ToString();
this.Text = "IP: " + ip;
textBox1.Text = ip;
}
private void Send(string s)
{
StreamWriter gui = new StreamWriter(client.GetStream());
gui.WriteLine(s);
gui.Flush();
}
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
if (client.Connected) Send(commandType.NgatKetNoi.ToString());
}
private void button1_Click(object sender, EventArgs e)
{
if (!client.Connected && button1.Text == "&Ok")
{
try
{
client.Connect(textBox1.Text, 8080);
StreamWriter gui = new StreamWriter(client.GetStream());
gui.WriteLine(commandType.KetNoi.ToString() + "$" + ip);
gui.Flush();
gui = null;
if (client.Client.Connected)
{
list.Items.Add("Đã kết nối...");
nghe = new Thread(new ThreadStart(langnghe));
nghe.Start();
send.Enabled = true;
chat.Enabled = true;
textBox1.Enabled = false;
button1.Text = "&Ngắt...";
hệThốngToolStripMenuItem.Enabled = true;
fileToolStripMenuItem.Enabled = true;
runToolStripMenuItem.Enabled = true;
}
}
catch (Exception err)
{
MessageBox.Show(err.Message.ToString(), "Loi ket noi");
}
}
else if (button1.Text == "&Ngắt...")
{
button1.Text = "&Ok";
Send(commandType.NgatKetNoi.ToString());
start(Application.ExecutablePath);
Application.Exit();
}
}
private void start(string s)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = s;
startInfo.ErrorDialog = true;
using (Process process = new Process())
{
process.StartInfo = startInfo;
try
{
process.Start();
}
catch (Exception ex)
{
MessageBox.Show("Lỗi: " + ex.ToString(), "Error");
}
}
}
Lấy dữ liệu từ server
public void langnghe()
{
nhan = new Thread(new ThreadStart(nhadulieu));
nhan.Start();
}
private void nhadulieu()
{
try
{
byte[] data = new byte[1024];
int receiv = 0;
String Stringdata;
NetworkStream stream = new NetworkStream(client.Client);
while (true)
{
receiv = client.Client.Receive(data);
Stringdata = Encoding.UTF8.GetString(data, 0, receiv).TrimEnd();
String[] s = Stringdata.Split('$');
if (s[0] == commandType.NgatKetNoi.ToString())
{
list.Items.Add("Đã ngắ