CHƯƠNG V: LẬP TRÌNH SOCKET BẤT ĐỒNG BỘ
VII.3. L ậP TRÌNH S OCKET BấT ĐồNG Bộ Sử DụNG TIểU TRÌNH
VII.3.1. Lập trình sử dụng hàng đợi gởi và hàng đợi nhận thông điệp
Trong cách lập trình này, chúng ta sẽ dùng hai hàng đợi, một hàng đợi gởi và một hàng đợi nhận để thực hiện việc gởi và nhận dữ liệu. Lớp Queue nằm trong namespace System.Collections giúp ta thực hiện việc này.
Queue inQueue = new Queue();
Queue outQueue = new Queue();
Hai phương thức quan trọng của lớp Queue được dùng trong lập trình mạng là EnQueue() và DeQueue(). Phương thức EnQueue() sẽ đưa một đối tượng vào hàng đợi và phương thức DeQueue() sẽ lấy đối tượng đầu tiên từ hàng đợi ra.
Ý tưởng của phương pháp lập trình này là ta sẽ dùng hai vòng lặp vô hạn để kiểm tra hàng đợi gởi và hàng đợi nhận, khi hàng đợi gởi có dữ liệu thì dữ liệu đó được gởi ra ngoài mạng thông qua Socket, tương tự khi hàng đợi nhận có dữ liệu thì nó sẽ ngay lập tức lấy dữ liệu đó ra và xử lý.
private void Send() {
while (true) {
if (OutQ.Count > 0) {
streamWriter.WriteLine(OutQ.Dequeue().ToString());
streamWriter.Flush();
} }
}
private void Receive() {
string s;
while (true) {
s = streamReader.ReadLine();
InQ.Enqueue(s);
} }
Để chạy song song hai vòng lặp vô hạn này ta phải tạo ra hai tiểu trình riêng, mỗi vòng lặp vô hạn sẽ chạy trong một tiểu trình riêng biệt do đó trong khi hai vòng lặp vô hạn này chạy thì tiến trình chính vẫn có thể làm đƣợc các công việc khác.
Trang 147
Thread tSend = new Thread(new ThreadStart(Send));
tSend.Start();
Thread tReceive = new Thread(new ThreadStart(Receive));
tReceive.Start();
Ngoài ra, ta còn sử dụng một tiểu trình khác thực hiện việc kết nối nhằm tránh gây treo tiến trình chính.
Thread tConnect = new Thread(new ThreadStart(WaitingConnect));
tConnect.Start();
Việc điều khiển kết nối đƣợc thực hiện trong một tiểu trình khác và đƣợc xử lý bằng phương thức WaitingConnect():
private void WaitingConnect() {
tcpListener = new TcpListener(1001);
tcpListener.Start();
socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected) {
MessageBox.Show("Client Connected");
netWorkStream = new NetworkStream(socketForClient);
streamReader = new StreamReader(netWorkStream);
streamWriter = new StreamWriter(netWorkStream);
tSend = new Thread(new ThreadStart(Send));
tSend.Start();
tReceive = new Thread(new ThreadStart(Receive));
tReceive.Start();
} else {
MessageBox.Show("Ket noi khong thanh cong");
} }
Trang 148
Việc nhập dữ liệu được thực hiện bằng phương thức InputData() public void InputData(string s)
{
InQ.Enqueue(s);
OutQ.Enqueue(s);
}
Phương thức này đơn giản chỉ đưa dữ liệu nhập vào hàng đợi nhận để hiển thị dữ liệu lên màn hình và đƣa dữ liệu nhập này vào hàng đợi gởi để gởi ra ngoài mạng.
Lớp ServerObject
using System;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Collections;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
namespace Server {
class ServerObject {
Thread tSend, tReceive, tConnect;
public Queue InQ = new Queue();
public Queue OutQ = new Queue();
private TcpListener tcpListener;
Socket socketForClient;
private NetworkStream netWorkStream;
private StreamWriter streamWriter;
private StreamReader streamReader;
public void CreateConnection() {
tConnect = new Thread(new ThreadStart(WaitingConnect));
tConnect.Start();
}
private void WaitingConnect() {
tcpListener = new TcpListener(1001);
Trang 149
tcpListener.Start();
socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected) {
MessageBox.Show("Client Connected");
netWorkStream = new NetworkStream(socketForClient);
streamReader = new StreamReader(netWorkStream);
streamWriter = new StreamWriter(netWorkStream);
tSend = new Thread(new ThreadStart(Send));
tSend.Start();
tReceive = new Thread(new ThreadStart(Receive));
tReceive.Start();
} else {
MessageBox.Show("Ket noi khong thanh cong");
}
//socketForClient.Close();
}
private void Send() {
while (true) {
if (OutQ.Count > 0) {
streamWriter.WriteLine(OutQ.Dequeue().ToString());
streamWriter.Flush();
} } }
private void Receive() {
string s;
while (true) {
s = streamReader.ReadLine();
InQ.Enqueue(s);
} }
Trang 150
public void InputData(string s) {
InQ.Enqueue(s);
OutQ.Enqueue(s);
} } }
Lớp ClientObject
using System;
using System.Windows.Forms;
using System.Collections;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace Client {
class ClientObject {
Thread tSend, tReceive, tConnect;
public Queue InQ = new Queue();
public Queue OutQ = new Queue();
private TcpClient socketForServer;
private NetworkStream networkStream;
private StreamWriter streamWriter;
private StreamReader streamReader;
public void Connect() {
tConnect = new Thread(new ThreadStart(WaitConnect));
tConnect.Start();
}
public void WaitConnect() {
try {
Trang 151
socketForServer = new TcpClient("localhost", 1001);
}
catch {
MessageBox.Show("Ket noi that bai");
}
networkStream = socketForServer.GetStream();
streamReader = new StreamReader(networkStream);
streamWriter = new StreamWriter(networkStream);
tSend = new Thread(new ThreadStart(Send));
tSend.Start();
tReceive = new Thread(new ThreadStart(Receive));
tReceive.Start();
}
private void Send() {
while (true) {
if (OutQ.Count > 0) {
streamWriter.WriteLine(OutQ.Dequeue().ToString());
streamWriter.Flush();
} } }
private void Receive() {
string s;
while (true) {
s = streamReader.ReadLine();
InQ.Enqueue(s);
} }
public void InputData(string s) {
InQ.Enqueue(s);
OutQ.Enqueue(s);
} } }