1.1 Sử dụng TCP một cách bất đồng bộ
V
VBạn cần ghi dữ liệu ra network-stream từng khối một, mà không phải block
phần mã lệnh còn lại. Kỹ thuật này có thể được sử dụng nếu bạn muốn
“stream” một file lớn trên mạng.
#
#Tạo một lớp riêng để xử lý kỹ thuật streaming bất đồng bộ. Bạn có thể bắt đầu
“stream” một khối dữ liệu bằng phương thức NetworkStream.BeginWrite và
cung cấp một phương thức callback. Khi callback được kích hoạt thì gửi khối
kế tiếp.
Lớp NetworkStream hỗ trợ việc sử dụng bất đồng bộ thông qua phương thức BeginRead
và BeginWrite. Sử dụng các phương thức này, bạn có thể
gửi hay nhận một khối dữ liệu
trên một trong các tiểu trình do thread-pool của bộ thực thi .NET cung cấp, mà không
block mã lệnh của bạn. Mục này trình bày kỹ thuật ghi bất đồng bộ.
Khi gửi dữ liệu một cách bất đồng bộ, bạn phải gửi dữ liệu nhị phân thô (một mảng byte).
Và bạn cần chọn kích thước mỗi lần gửi hay nhận. Ví dụ dưới đây vi
ết lại server từ mục
11.11 sao cho mỗi lớp ClientHandler gửi một lượng lớn dữ liệu được đọc từ một file. Dữ
liệu này được gửi một cách bất đồng bộ, nghĩa là ClientHandler có thể tiếp tục thực hiện
các tác vụ khác (trong ví dụ này, nó chỉ việc lấy các thông điệp được gửi từ client).
Một thuận lợi của cách tiếp cận này là toàn bộ nộ
i dung của file chẳng bao giờ nằm trong
bộ nhớ một lượt. Thay vào đó, nó được thu lấy ngay trước khi một khối mới được gửi.
Một thuận lợi khác nữa là server có thể hủy bỏ thao tác vào bất cứ lúc nào. Ví dụ, nếu
this.buffer = new byte[bufferSize];
this.client = client;
this.ID = ID;
}
public void Start() {
// Thu lấy network stream.
networkStream = client.GetStream();
// Tạo các đối tượng dùng để gửi và nhận text.
BinaryWriter w = new BinaryWriter(networkStream);
BinaryReader r = new BinaryReader(networkStream);
if (r.ReadString() == ClientMessages.RequestConnect) {
w.Write(ServerMessages.AcknowledgeOK);
Console.WriteLine(ID + ": Connection completed.");
string message = "";
while (message != ClientMessages.Disconnect) {
message = r.ReadString();
if (message == ClientMessages.RequestData) {
// Tên file có thể do client cung cấp, nhưng
// trong ví dụ này, file thử nghiệm là mã cứng.
fileStream =
new FileStream("test.bin", FileMode.Open);
networkStream.EndWrite(asyncResult);
}
// Lấy khối kế tiếp từ file.
int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
// Nếu không đọc được byte nào, stream đã đến cuối file.
if (bytesRead > 0) {
Console.WriteLine("Streaming new block.");
// Ghi khối kế tiếp ra network stream.
networkStream.BeginWrite(buffer, 0, buffer.Length,
new AsyncCallback(StreamData), null);
} else {
// Kết thúc thao tác.
Console.WriteLine("File streaming complete.");
fileStream.Close();
}
}
}
Bạn có thể sử dụng một mẫu tương tự để đọc dữ liệu một cách bất đồng bộ phía client.
1.2 Giao tiếp bằng UDP
V
VBạn cần gửi dữ liệu giữa hai máy tính trên một network bằng User Datagram
Protocol (UDP) stream.
private static int localPort;
private static void Main() {
// Định nghĩa endpoint (thông điệp được gửi tại đây).
Console.Write("Connect to IP: ");
string IP = Console.ReadLine();
Console.Write("Connect to port: ");
int port = Int32.Parse(Console.ReadLine());
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(IP),
port);
// Định nghĩa endpoint cục bộ (thông điệp được nhận tại đây).
Console.Write("Local port for listening: ");
localPort = Int32.Parse(Console.ReadLine());
Console.WriteLine();
// Tạo một tiểu trình mới để nhận thông điệp đến.
Thread receiveThread = new Thread(
new ThreadStart(ReceiveData));
receiveThread.IsBackground = true;
receiveThread.Start();
UdpClient client = new UdpClient();
try {
string text;
do {
string text = Encoding.UTF8.GetString(data);
// Hiển thị text thu được.
Console.WriteLine(">> " + text);
} catch (Exception err) {
Console.WriteLine(err.ToString());
}
}
}
}
Chú ý rằng, các ứng dụng UDP không thể sử dụng NetworkStream như các ứng dụng
TCP. Thay vào đó, chúng phải chuyển tất cả dữ liệu thành một stream bằng một lớp mã
hóa, như đã được mô tả trong mục 2.2.
Bạn có thể thử nghiệm ứng dụng này với các client trên máy cục bộ bằng cách sử dụng
hai port khác nhau và địa chỉ loopback. Ví dụ, giả sử có hai UDP-client: client A và client
B. Dưới
đây là transcript đối với client A:
Connect to IP: 127.0.0.1
Connect to port: 8001
Local port for listening: 8080
Hi there!
Và đây là transcript tương ứng đối với client B (cùng với thông điệp nhận được):
Connect to IP: 127.0.0.1
Connect to port: 8080
Local port for listening: 8001
>> Hi there!
1.3 Gửi e-mail thông qua SMTP
V
MailAttachment myAttachment = new MailAttachment("c:\\mypic.gif");
myMessage.Attachments.Add(myAttachment);
Để gửi thông điệp, bạn chỉ cần cho biết tên của SMTP-server và gọi phương thức
SmptMail.Send.
SmtpMail.SmtpServer = "test.mailserver.com";
SmtpMail.Send(myMessage);
Tuy nhiên, có một vài vấn đề khi sử dụng lớp SmtpMail để gửi một thông điệp e-mail.
Lớp này cần một SMTP-server cục bộ hay một relay-server trên mạng. Ngoài ra, lớp
SmtpMail không hỗ trợ việc xác thực, do đó, nếu SMTP-server yêu cầu username và
password, bạn sẽ không thể gửi bất kỳ mail nào. Để khắc phục vấn đề này, bạn có thể
trực tiếp sử dụng thành phần
CDOSYS thông qua COM Interop (giả sử bạn có phiên bản
server của Windows hay Microsoft Exchange).
# Nhớ rằng, giao thức SMTP không được sử dụng để lấy e-mail. Đối với công việc
này, bạn cần giao thức POP3 hay IMAP, cả hai giao thức này đều không có
trong .NET Framework.
Để có thêm thông tin về cách sử dụng và cấu hình SMTP-server, bạn hãy tham
khảo các quyển sách chuyên về IIS.
1.4 Gửi và nhận e-mail với MAPI
V
VBạn muốn gửi một thông điệp e-mail, nhưng SMTP-server (Simple Mail
Transfer Protocol server) chưa được cấu hình trên máy tính.
#
#Sử dụng Simple MAPI (Messaging Application Programming Interface) bằng