Bắt sự kiện bật, tắt chương trình. Event start, stop process


thuvienwinform - C# hỗ trợ người lập trình biết được chương trình nào vừa được bắt đầu, chương trình nào vừa kết thúc thông qua sự kiện EventArrivedEventHandler của ManagementEventWatcher nằm trong bộ thư viện System.Management. Để bắt được các sự kiện này, đầu tiên chương trình phải có quyền admin. Để thực hiện gán quyền admin cho chương trình xem thêm tại: http://thuvienwinform.blogspot.com/2013/09/item-manifes-tchay-ung-dung-winform-voi-quyen-admin.html

Project demo: https://www.dropbox.com/s/es33d1d5413oqop/thuvienwinform-ManagermentEventWatcher%28KiemTraSuThayDoiCuaTaskMgr%29.rar

Sau khi thêm quyền admin cho chương trình, ta thoát visual ra và chạy lại nó với quyền admin
Chú ý: nếu không sử dụng được ManagementEventWatcher thì phải thực hiện Add reference System.Management bằng tay
Rồi, ok code như sau:
1. Bắt sự kiện chương trình mới được bật lên

void ChuongTrinhBat()
{
    WqlEventQuery q = new WqlEventQuery("Win32_ProcessStartTrace");
    ManagementEventWatcher w = new ManagementEventWatcher(q);
    w.EventArrived += new EventArrivedEventHandler(voidChuongTrinhBat);
    w.Start();
}

private void voidChuongTrinhTat(object sender, EventArrivedEventArgs e)
{
    string s = "";
    foreach (var pd in e.NewEvent.Properties)
        if(pd.Value != null)
            if (pd.Name == "ProcessName")// ngoai ra con co ProcessID, TIME_CREATED
                s += pd.Value.ToString() + "\n";
    MessageBox.Show("Co mot chuong trinh vua moi tat\n" + s);
}

2. Bắt sự kiện chương trình bị tắt đi

void ChuongTrinhTat()
{
    ManagementEventWatcher w1 = new ManagementEventWatcher("select ProcessName from Win32_ProcessStopTrace");
    w1.EventArrived += new EventArrivedEventHandler(voidChuongTrinhTat);
    w1.Start();
}
private void voidChuongTrinhBat(object sender, EventArrivedEventArgs e)
{
    string s = "";
    foreach (var pd in e.NewEvent.Properties)
        if (pd.Value != null)
            if (pd.Name == "ProcessName")// ngoai ra con co ProcessID, TIME_CREATED
                s += pd.Value.ToString() + "\n";
    MessageBox.Show("Co mot chuong trinh vua moi bat\n" + s);
}

- Ngoài ra có thể chỉnh lại cái đoạn select một chút để lấy những giá trị cần thiết như:
+ Lấy ProcessName: select ProcessName from Win32_ProcessStopTrace
+ Lấy thời gian: select TIME_CREATE from Win32_ProcessStartTrace
+...
5/31/2014
Đăng bởi :
Nhãn :

[CODE] Truyền dữ liệu qua lại giữa các Process và ứng dụng

thuvienwinform - Xin chào ! Hôm nay mình sẽ hướng dẫn truyền dữ liệu qua lại giữa các Process. Việc này tưởng như không quan trọng lắm nhưng thực ra nó rất cần thiết khi code các phần mềm liên quan tới quản lí máy tính như Antivirus....

I. Vấn đề
Chắc hẳn các bạn đã dùng nhiều phần mềm diệt virus và thấy luôn có 1 exe riêng cho Tray (chạy dưới khay taskbar). Hãy tự hỏi tại sao lại phải tách riêng ra như vậy mà không code gộp vào 1 exe cho dễ quản lí ???
Đơn giản thôi, vì cái Tray đó làm nhiệm vụ quản lí Runtime (thời gian thực -- chạy liên tục cùng máy tính) và nếu gộp vào thì sẽ rất ngốn RAM (Ram sẽ phải load cả phần giao diện ...) nên để hệ thống chạy "êm và không nặng nề" người ta đã làm Tray ra 1 exe riêng biệt . ^^ và bây giờ việc truyền dữ liệu giữa Process là vấn đề quan trọng

II. Giải quyết
Thời còn .NET Framework 3.0 trở xuống người ta vẫn phải truyền dữ liệu qua lại giữa Process thông qua File. Nhưng tới .NET 3.5 , đã có 1 công nghệ xuất hiện để giải quyết vấn đề này.

Hôm nay mình sẽ giới thiệu vs các bạn công nghệ Pipes - công nghệ này chạy theo mô hình Server/Client
(using System.IO.Pipes) tức là 1 process sẽ đóng vai trò như 1 máy chủ, các process khác gửi nhận dữ liệu thông qua Server.

Xem 1 ví dụ đơn giản nhé (Ví dụ vẫn là cách học dễ nhất nhỉ ^^)

* Server :
Form server của mình có 1 textbox và 1 nút
(ấn vào button sẽ gửi data trong textbox cho Client)
 
// Biến Server
private NamedPipeServerStream sv;

        public Server()
        {
            InitializeComponent(); 
        }

        private void Server_Load(object sender, EventArgs e)
        {
                   // Tạo server có tên "ServerTest"
            sv = new NamedPipeServerStream("ServerTest", PipeDirection.InOut);
                   // Đợi 1 client khác kết nối
            sv.WaitForConnection();
        }

        private void button1_Click(object sender, EventArgs e)
        {
              // Khi ấn Button1 - Gửi dữ liệu cho client (phải gửi dạng byte nhé)
            var data = Encoding.Unicode.GetBytes(this.textBox1.Text);
            sv.Write(data, 0, data.Length);
 
        }

* Client



Form Client chỉ có 1 ricktexbox để cập nhật


// Client
NamedPipeClientStream stream;

        public Client()
        {
            InitializeComponent();
            
        }

        private void Client_Load(object sender, EventArgs e)
        {
                 // Kết nối tới "ServerTest"
            stream = new NamedPipeClientStream("ServerTest");
            stream.Connect();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // Timer này cập nhật dữ liệu liên tục dưa vào RickTextbox mình đã tạo
            var re = new byte[1000];

            stream.Read(re, 0, 1000);
            string data = Encoding.Unicode.GetString(re);

            if (data != "")
                richTextBox1.Text += "\n" + data;
        }

Chạy server trước, sau đó chạy client và thử nhé ^^!

Ô xong rồi ^^!
Vậy đã truyền được dữ liệu giữa các process ^^
5/06/2014
Đăng bởi :
Nhãn :

[Code] Xử lí sự kiện cho nhiều Control

thuvienwinform - Chào ! Khi tạo form chắc hẳn bạn sẽ gặp rất nhiều control mà sẽ dùng chung một sự kiện. Nhất là đối với các hiệu ứng cho các control (Ví dụ như sự kiện MouseMove và MouseLeave...) Hôm nay chúng ta sẽ giải quyết vấn đề này. Cũng dễ thôi ^^

 I. VẤN ĐỀ 
Đối với một Form có rất nhiều Control ... và bạn muốn Form "Lung linh" hơn thì cần thêm hiệu ứng cho các Control trong Form. Ví dụ như khi trỏ chuột vào Lable thì chữ nó đậm lên - khi ngừng trỏ thì quay lại như ban đầu. >> Bình thường bạn phải tạo từng sự kiện cho từng Lable (mỗi Lable 2 sự kiện lận đó .. điều này tương đương với 2 procedure nhỏ) Mà ví dụ như có 100 Label thì sao nhỉ --> 200 sự kiện OMG ... Đủ chết rồi đấy ^^

II. GIẢI QUYẾT 
Đơn giản thôi, ở đây chúng ta sẽ tạo ra một lớp có đầy đủ các sự kiện ... và sau đó chỉ cần truyền Control vào lớp này là xong ^^! Bắt đầu nhé : Ở đây mình sẽ tạo lớp XULIHIEUUNG như sau :
 
public class XULIHIEUUNG
    {
        Control g_Control;

        public void TAOHIEUUNG(Control c)
        {
            g_Control = c;
            btn.MouseMove += new System.Windows.Forms.MouseEventHandler(MouseMoveEvent);
            btn.MouseLeave += new System.EventHandler(MouseLeaveEvent);
        }
        public void MouseMoveEvent(object sender, EventArgs e)
        {
            g_Control.Text = "Ô bắt được con chuột";
        }
        public void MouseLeaveEvent(object sender, EventArgs e)
        {
            g_Control.Text = "Chuột chạy mất rồi";
        }
    }

Trong hàm khởi tạo form chỉ cần thêm code sau bạn chỉ cần thêm code sau đây :

 new XULIHIEUUNG().TAOHIEUUNG(button1); 

 Bây giờ thử mở Form ra coi... Khi bạn trỏ chuột vào button1 và khi di chuyển chuột ra khỏi chỗ đó .. Xem thế nào :)) (1 dòng này = 6 dòng code tay đấy, chưa kể phải mở Properties của từng Control mà chọn sự kiện)

 OK, vậy là xong rồi. Đơn giản đúng không :D
5/04/2014
Đăng bởi :
Nhãn :

Thêm thuộc tính, sự kiện cho các điểu khiển trong winform

thuvienwinform - Apply Attributes in Windows Forms Controls (áp dụng các thuộc tính vào các điều khiển trong winform) sẽ giúp chúng ta thêm những sự kiện, thuộc tính chúng ta cần vào các control này. Ví dụ như thêm tính năng chuẩn hóa cho textBox, hoặc giới hạn độ dài cho textBox. Rất tiện trong quá trình code và sau này, tức là dùng cho được nhiều sản phẩm. Chính vì sự hữu ích này, hôm nay mình xin được chia sẻ cách thêm thuộc tính và sự kiện cho các điều khiển trong winform.


Tải về project demo: https://www.dropbox.com/s/6ih1d0oephk97r2/thuvienwinform-ThemThuocTinhChoControl.rar (46KB)

Bài viết này sẽ giới thiệu việc thêm tính năng chuẩn hóa và giới hạn độ dài cho TextBox. Gồm 2 phần
- Phần I: Thêm thuộc tính, sự kiện cho 1 điều khiển dựa trên lớp kế thừa
- Phần II: Tạo 1 điều khiển chứa nhiều điều khiển (từ các điều khiển đã có)

Chú ý: nếu tải về mở ra lỗi thì ấn F5 cho nó chạy sẽ hết lỗi (Do nó chưa nạp các điều khiển tự tạo vào)
- Để đọc code dễ ấn chuột phải vào code -> Outlining -> Collapse to Definitions (Ctrl + M,O).
- Để xem code của cotrol không có Design: ấn F7 hoặc ấn vào Switch to code...

I. Thêm thuộc tính, sự kiện cho 1 điều khiển

1. Thêm thuộc tính


- Rất đơn giản thôi. Đầu tiên thêm 1 class với tên: MyTextBox

- Class này kế thừa của TextBox


- Sau đó ta thêm các thuộc tính cho MyTextBox như sau:

[Category("Thuộc tính xây dựng thêm")]
[Description("Chuẩn hóa văn bản nhập vào. Viết hoa kí tự sau dấu cách")]
[DefaultValue(true)]
public bool ChuanHoa
{
    get;
    set;
}

private DoDai _doDai;//Cái này phục vụ cho việc thêm sự kiện sau này
[Category("Thuộc tính xây dựng thêm")]
[Description("Định độ dài cho văn bản \nNgắn: 30 kí tự\nBình thường: 60 kí tự\nDài:255 kí tự")]
public DoDai ĐộDài
{
    get { return _doDai; }
    set{_doDai = value;}
}

Với DoDai là 1 enum

public enum DoDai
{
    Ngắn,
    BìnhThường,
    Dài,
    TốiĐa
}

Trở lại phần thiết kế ta đã có được như này


2. Xây dựng chức năng chuẩn hóa, giới hạn độ dài

a. Chuẩn hóa
- Chúng ta sẽ chuẩn hóa sau khi nhập chữ vào MyTextBox xong. Sử dụng sự kiện LostFocus và ấn nút Enter để thực hiện chuẩn hóa. this.Text = ChuanHoaXau(this.Text);

protected override void OnLostFocus(EventArgs e)
{
    base.OnLostFocus(e);
    ThucHienChuanHoa();
}

protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
    base.OnKeyDown(e);
    //Ấn enter
    if (e.KeyCode == System.Windows.Forms.Keys.Enter)
        ThucHienChuanHoa();
}

private void ThucHienChuanHoa()
{
    //Chuẩn hóa xâu trong textBox
    this.Text = ChuanHoaXau(this.Text);//Các hàm còn lại xem trong project demo nha
    //Đưa con trỏ nhấp nháy về cuối dòng
    this.Select(this.Text.Length, this.Text.Length);
}

Kết quả:


b. Giới hạn độ dài
- Để giới hạn độ dài ta sử dụng sự kiện TextChanged
protected override void OnTextChanged(EventArgs e)
{
    base.OnTextChanged(e);
    int doDaiToiDa = 0;
    switch (ĐộDài)
    {
        case DoDai.Ngắn         : doDaiToiDa = 30; break;
        case DoDai.BìnhThường   : doDaiToiDa = 60; break;
        case DoDai.Dài          : doDaiToiDa = 255; break;
        default: break;
    };
    if (ĐộDài != DoDai.TốiĐa)
        if (this.Text.Length > doDaiToiDa)
            ThietLapDoDai(doDaiToiDa);
}

/// <summary>
/// Thiết lập độ dài kí tự trong textBox
/// </summary>
/// <param name="ddtd">Độ dài tối đa cho phép</param>
private void ThietLapDoDai(int ddtd)
{
    //Dữ lại đoạn văn bản cho phép
    this.Text = this.Text.Substring(0, ddtd);
    //Đưa con trỏ nhấp nháy về cuối dòng
    this.Select(ddtd, ddtd);
}

- Cách này khá thủ công như có lẽ như vậy sẽ dễ hiểu hơn. Để tối ưu thì ta sửa luôn việc set get biến Text của TextBox. Chuẩn hóa luôn khi set get

3. Bắt sự kiện thay đổi giá trị ĐộDài

a. Sử dụng delegate EventHandler
- Tạo sự kiện
public event EventHandler ThayDoiDoDai;//Khai báo sự kiện

- Code cho sự kiện
protected virtual void OnThayDoiDoDai()
{
    EventHandler handler = this.ThayDoiDoDai;
    if (handler != null)
    {
        handler(this, EventArgs.Empty);
    }
}

- OK. Đã có sự kiện! Bây giờ đặt vào chỗ cần thực hiện sự kiện. Đó là khi giá trị ĐộDài thay đổi. Là lúc nào nhỉ?? Chính là lúc set get giá trị cho nó
public DoDai ĐộDài
{
    get { return _doDai; }
    set
    {
        _doDai = value;
        //Mỗi khi thay đổi giá trị -> set, get 1 lần => chính là sự kiện thay đổi giá trị
        OnThayDoiDoDai();
    }
}


b. Tạo lớp kế thừa của EventHandler để tạo thêm các giá trị cho sự kiện
- Ví như sự kiện CellClick của DataGridView có thể lấy giá trị hàng (e.RowIndex). Vậy làm như thế nào để thêm các thuộc tính cho sự kiện. Ta cần tạo 1 lớp kế thừa của thằng EventHandler như sau:
//Tạo class bằng file mới hoặc trong cùng class MyTextBox đều được. Xem thêm trong project demo
public class ThayDoiGiaTriDoDai : EventArgs
{
    public DoDai GiaTriDoDai { get; set; }
    public bool DuocChuanHoa { get; set; }
    public string ThongTinChoSuKien
    {
        get { return "Sự kiện thay đổi giá trị độ dài của MyTextBox"; }
    }
}

- Thêm sự kiện sử dụng lớp kế thừa này
[Category("Sự kiện Xây dựng thêm")]
[Description("Bắt sự kiện thay đổi độ dài. Dùng class kế thừa")]
public event EventHandler<ThayDoiGiaTriDoDai> ThayDoiDoDaiDungClass;//Khai báo sự kiện
/// <summary>
/// Code cho sự kiện
/// </summary>
/// <param name="s">Nạp giá trị đầu vào để hiển thị ra khi sử dụng sự kiện</param>
protected virtual void OnThayDoiDoDai(ThayDoiGiaTriDoDai s)
{
    EventHandler<ThayDoiGiaTriDoDai> handler = this.ThayDoiDoDaiDungClass;
    if (handler != null)
    {
        handler(this, s);
    }
}

- OK bây giờ sửa lại lúc set get là được
public DoDai ĐộDài
{
    get { return _doDai; }
    set
    {
        _doDai = value;
        //Mỗi khi thay đổi giá trị -> set, get 1 lần => chính là sự kiện thay đổi giá trị
        SuKien = new ThemThuocTinhChoControl.ThayDoiGiaTriDoDai();
        SuKien.GiaTriDoDai = this.ĐộDài;
        SuKien.DuocChuanHoa = this.ChuanHoa;
        OnThayDoiDoDai(SuKien);
    }
}

- Kết quả:



II. Tạo UserControl từ các control khác

- Trong thực tế có nhiều form ta có các kiểu bố trí giống nhau, có sự kết hợp của nhiều control giống nhau. Ví dụ như tập hợp các textBox để nhập thông tin họ tên ngày sinh,...thì ta chỉ cần tạo 1 lần vào sử dụng cho các form khác nhau. Để thực hiện việc này ta làm như sau:

- Tạo 1 UserControl

- Sau đó thì kéo các điều khiển khác vào

- Ok có thể nói là xong rùi nhưng ta muốn thêm các thuộc tính, sự kiện cho thằng này thì làm tương tự phần I là OK.
- Ví dụ thêm thuộc tính tự động Anchor:
public bool TuDongDanCachCacPhanTu
{
    get { return _tuDongDanCachCacPhanTu; }
    set 
    { 
        _tuDongDanCachCacPhanTu = value;
        if (_tuDongDanCachCacPhanTu)
        {
            this.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;//This ở đây là UserCOntrol
            this.myTextBox1.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
            this.myTextBox2.Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
        }
        else
        {
            this.Anchor = AnchorStyles.Top | AnchorStyles.Left;
            this.myTextBox1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
            this.myTextBox2.Anchor = AnchorStyles.Top | AnchorStyles.Left;
        }
    }
}
- Sau khi đã thêm tạo được các file cs chỉ cần thêm vào các project khác là ok.

Nếu thấy hữu ích hãy để lại bình luận hoặc ấn G+. Cảm ơn các bạn đã đọc bài viết
4/25/2014
Đăng bởi :

LINQ to Sqlite, LINQ to MySQL, LINQ to Oracle

thuvienwinform - SQLite mà mình thấy nó quá tuyệt với rồi! Bây giờ lại phát hiện ra bộ kết nối giữa C# với SQLite bằng LINQ nữa, tốc độ code phải tăng gấp 10 lần mất, không tù tội như hồi trước xài ADO.NET nũa (nói thế hơi quá nhưng ADO.NET phải chạy mới biết lỗi). Nó chính là bộ LinqConnect. Các bạn có thể tải về bản đầy đủ tất cả LINQ to X với X = {SQLite, MySQL, Oracle,...} :D. Việc sử dụng tương tự như LINQ to SQL, cũng kéo thả, sinh code tự động.


Tải về (44MB):
- Dropbox: https://www.dropbox.com/s/bo88kvu7b6s2w8a/linqconnectfree.exe
- MediaFire: http://www.mediafire.com/download/2sjr3jxegugb1t1/linqconnectfree.exe

Trước khi cài thoát Visual Studio ra nha. Sau khi cài xong thì add item nó sẽ có cái này:


Tạo CSDL bằng SQLite: http://thuvienwinform.blogspot.com/2013/10/SQLite-chay-ung-dung-su-dung-da-tabase-tren-may-khong-cai-sql.html

Hướng dẫn: http://www.devart.com/dotconnect/sqlite/articles/tutorial_linq.html#model

Chú ý khi sử dụng
- Nhập đúng namspace. Bình thường cứ quen tay next next là hỏng đấy :D



Còn việc thêm, sửa, xóa thì giống hệt trong LINQ to SQL:
- Nạp, thêm dữ liệu: http://thuvienwinform.blogspot.com/2014/01/linq-to-sql-bai-1-load-va-them-du-lieu.html
- Sửa dữ liệu: http://thuvienwinform.blogspot.com/2014/01/linq-to-sql-bai-2-sua-du-lieu.html
- Xóa dữ liệu: http://thuvienwinform.blogspot.com/2014/01/linq-to-sql-bai-3-xoa-du-lieu.html

Chú ý:
Muốn sang máy khác chạy được cần copy toàn bộ thư viện (các tệp .dll) gồm:
1. Phần tự sinh của Devart

Devart.Data.dll
Devart.Data.Linq.dll
Devart.Data.SQLite.dll
Devart.Data.SQLite.Linq.dll
2. Phần lấy trong ổ cài của Devart: (mặc định: C:\Program Files (x86)\Devart\dotConnect\SQLite)
sqlite3.dll
thư mục x64

Tổng cộng bằng này cái:
Nếu không đủ sẽ gặp một số lỗi về như DbCommand..., version asembly...balabala

4/20/2014
Đăng bởi :
Nhãn : ,

CHAT LAN C#. Phần 3: Code máy khách (Client). Gửi, nhận dữ liệu với máy chủ

thuvienwinform - Sau khi đã có máy chủ thì chỉ việc tạo các máy khách kết nối đến máy chủ để giao tiếp với nhau thui. Sau khi tạo được kết nối thì máy khách sẽ gửi dữ liệu đến máy chủ và nhận dữ liệu truyền về! Đơn giản hơn code trên máy chủ rất nhiều.

Tải về project: https://www.dropbox.com/s/3moekk8knkge5s4/thuvienwinform-CHATLANClient.rar (18KB)

Yêu cầu:
- Kết nối chung mạng với máy cái ChatLanServer.
- Máy khách không cần Ip tĩnh

Cụ thể các bước xây dựng một máy khách như sau:
1/ Tạo luồng kết nối TcpClient
2/ Kết nối đến máy chủ với địa chỉ ip và cổng xác định (là ip tĩnh và cổng được tạo cho chương trình ChatLanServer trên máy chủ)
3/ Thực hiên giao tiếp với máy chủ
4/ Đóng kết nối

Các biến:

//Địa chỉ mặc định
string IP = "127.0.0.1";
int PORT = 100;

//Các luồng
Thread thKetNoiDenServer, thKetNoiTaoServer;

//Biến dùng để gửi, nhận dữ liệu
byte[] dlNhan = new byte[1024];
byte[] dlGui = new byte[1024];

TcpClient Khach;


1/ Tạo luồng kết nối TcpClient

Khach = new TcpClient();

2/ Kết nối đến máy chủ với địa chỉ ip và cổng xác định

Khach.Connect(IPAddress.Parse(IP), PORT);

3/  Thực hiên giao tiếp với máy chủ

- Nhận dữ liệu: TcpClient.GetStream().Read

string tmp = "";
byte[] dlNhan = new byte[1024];
Khach.GetStream().Read(dlNhan, 0, 1024);
tmp = Encoding.Unicode.GetString(dlNhan);

- Gửi dữ liệu: TcpClient.GetStream().Write

byte[] dlGui = new byte[1024];
dlGui = Encoding.Unicode.GetBytes(txtGui.Text);
Khach.GetStream().Write(dlGui, 0, dlGui.Length);

4/ Đóng kết nối

Thêm mô tả tìm kiếm và Liên kết cố định để SEO chuẩn :)
 
Khach.Close();



Nếu bạn mua IP tĩnh thì nó trở thành chat online là truyện bình thường :) cho máy cài IP tĩnh đó chạy chương trình server và các máy khách kết nối đến là được

19-5-2015:
Thực ra với C# có nhiều cách để xây dựng một ứng dụng truyền dữ liệu qua mạng kiểu này. Sử dụng socket là cái nền tảng sơ khai nhất, mình sẽ hướng dẫn một bài khác cũng về vấn đề truyền dữ liệu qua mạng này trên một công nghệ khác (WCF hoặc Remote) đơn giản hơn nhiều, các bạn theo dõi blog để nhận bài sớm nhất nhé!
4/19/2014
Đăng bởi :
Nhãn : ,

CHAT LAN C#. Phần 2: Code máy chủ (Server). Xử lí việc gửi nhận với nhiều máy khách

thuvienwinform - Để thực xây dựng chương trình gửi tin nhắn qua mạng LAN cần có một chương trình chạy trên máy chủ. Chức năng chính của nó là: Nhận kết nối từ các máy khách, sau khi tạo được kết nối thì bắt đầu việc gửi/nhận dữ liệu giữa máy chủ và máy khách. Khi nhận được dữ liệu (văn bản, hình ảnh, âm thanh,..) thì sẽ được xử lí trên máy chủ này. Có thể là lưu vào CSDL hoặc thực hiện các lệnh nhận được từ máy khách như gửi cho họ một tài liệu, hình ảnh, đoạn phim,...

Phần 1: [CHAT LAN] Phần 1: Giao thức TCP và System.NET. Những thành phần côt yếu để xây dựng chương trình chat qua mạng LAN

Tải project: https://www.dropbox.com/s/tydku6em1cjq8mb/thuvienwinform-CHATLANServer.rar (21KB)




Máy chủ dùng IP hiện tại của máy. Tham khảo thêm cách lấy IP này: http://thuvienwinform.blogspot.com/2013/10/code-lay-username-va-ip-cua-may.html


Cụ thể thì các bước để xây dựng một máy chủ như sau:
1/ Tạo (mở) một cổng kết nối logic (socket) để cho các máy khách tham gia gửi/nhận tin băng cổng này
2/ Đợi, lắng nghe và chấp nhận các kết nối từ máy khách
3/ Thực hiên giao tiếp với máy khách: Nhận dữ liệu từ máy khách, phân tích, xử lí sau đó gửi lại co máy khách. (lưu vào CSDL, chống nói tục@!, ...)
4/ Đóng socket



- Các code chat mạng LAN trên mạng thường thì bước 2 chỉ chấp nhận được 1 kết nối. Để chấp nhận nhiều kết nối thì ta cho bước 2 vào vòng lặp, khi kết nối thêm 1 khách sẽ chuyển bước 3 sang 1 luồng (thread) khác giao tiếp với máy khách đó.

- Trong này sử dụng khá nhiều về thread. Có thể xem thêm ở bài Thread trong C#: http://thuvienwinform.blogspot.com/2014/04/thread-trong-csharp.html


Các biến:

//Địa chỉ mặc định
string IP = "127.0.0.1";
int PORT = 100;

//Các luồng
Thread thKetNoiDenServer, thKetNoiTaoServer, thLienLacKhach;
TcpListener langNghe;

//Biến dùng để gửi, nhận dữ liệu
byte[] dlNhan = new byte[1024];
byte[] dlGui = new byte[1024];

//Socket tạo server và kết nối
Socket socket;
//Tạo 1 socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//Danh sách các máy khách kết nối đến
List cacMay = new List();

1/ Tạo (mở) một cổng kết nối logic (socket)

//Tạo 1 socket
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = new IPEndPoint(IPAddress.Parse(IP), PORT);//IP = "127.0.0.1"; PORT = 100;
//Liên kết cổng s với địa chỉ IP và cổng
s.Bind(iep);
//Nhận tín hiệu từ các máy kết nối
s.Listen(10);

Nếu có 1 IP tĩnh mua với nhà mạng thì chương trình này trở thành chat online luôn đó :)
2/ Đợi, lắng nghe và chấp nhận các kết nối từ máy khách


//Thêm máy khách
socket = s.Accept();

//Lưu máy khách được thêm vào danh sách. Để dễ quản lí
cacMay.Add(socket);

//Thông báo kết nối với máy khách
txtNoiDung.Text = txtNoiDung.Text + "Đã thêm 1 máy khách " + "\r\n";

//Mỗi máy khách sẽ được xử lí trong 1 luồng (thread)
ThreadPool.QueueUserWorkItem(GiaoTiepTungKhach, socket);

với List cacMay = new List();
Cài tiến code bước 2 này để nhận được kết nối từ nhiều máy khách:

//Trong khi còn kết nối. Mỗi khi có tín hiệu từ máy khách đến sẽ thêm vào -> nhận đc nhiều máy khách cùng lúc
while (true)
{
    //Thêm máy khách
    socket = s.Accept();

    //Lưu máy khách được thêm vào danh sách. Để dễ quản lí
    cacMay.Add(socket);

    //Thông báo kết nối với máy khách
    txtNoiDung.Text = txtNoiDung.Text + "Đã thêm 1 máy khách " + "\r\n";

    //Mỗi máy khách sẽ được xử lí trong 1 luồng (thread)
    ThreadPool.QueueUserWorkItem(GiaoTiepTungKhach, socket);
}


3/ Thực hiên giao tiếp với máy khách

- Nhận văn bản gửi đến lưu vào biến tạm tmp

string tmp = "";
byte[] dlNhan = new byte[1024];
socket.Receive(dlNhan);
tmp = Encoding.Unicode.GetString(dlNhan);

- Gửi văn bản đến các máy khách:

foreach (Socket s in cacMay)
{
    s.Send(Encoding.Unicode.GetBytes(noiDung));
}

Để gửi được hình ảnh thì ta chuyển ảnh thành byte[] xong cũng gửi bình thường. Xem cách chuyển: http://thuvienwinform.blogspot.com/2014/03/code-up-anh-len-csdl-su-dung-kieu-image-trong-sqlserver.html
4/ Đóng socket


Khach.Close();


Để chương trình hoạt động thì ngày mai sẽ có project máy khách cho các bạn nha :)
19-5-2015: Thực ra với C# có nhiều cách để xây dựng một ứng dụng truyền dữ liệu qua mạng kiểu này. Sử dụng socket là cái nền tảng sơ khai nhất, mình sẽ hướng dẫn một bài khác cũng về vấn đề truyền dữ liệu qua mạng này trên một công nghệ khác (WCF hoặc Remote) đơn giản hơn nhiều, các bạn theo dõi blog để nhận bài sớm nhất nhé!
4/18/2014
Đăng bởi :
Nhãn : ,

CHAT LAN C#. Phần 1: Giao thức TCP và System.NET. Những thành phần côt yếu để xây dựng chương trình chat qua mạng LAN

thuvienwinform - C# hỗ trợ chúng ta lập trình mạng rất tốt, cụ thể là có thư viện System.Net. Qua đó chúng ta có thể xây dựng những ứng dụng hữu ích để gửi, nhận dữ liệu qua mạng. Một ví dụ điển hình cho việc lập trình mạng là chương trình gửi tin nhắn (chat) qua mạng LAN. Cũng đơn giản thui từ từ từng bước một là OK. Để xây dựng chương trình này trước hết chúng ta cần tìm hiểu về giao thức hoạt động để gửi/nhận dữ liệu TCP và System.NET

1. TCP

Wikipedia:
- TCP là giao thức cốt lõi của bộ giao thức TCP/IP. Sử dụng TCP, ử dụng TCP, các ứng dụng trên các máy chủ được nối mạng có thể tạo các "kết nối" với nhau, mà qua đó chúng có thể trao đổi dữ liệu hoặc các gói tin. Giao thức này đảm bảo chuyển giao dữ liệu tới nơi nhận một cách đáng tin cậy và đúng thứ tự. TCP còn phân biệt giữa dữ liệu của nhiều ứng dụng (chẳng hạn, dịch vụ Web và dịch vụ thư điện tử) đồng thời chạy trên cùng một máy chủ. Xem thêm...
- TCP hỗ trợ nhiều giao thức ứng dụng phổ biến trên Internet và các ứng dụng kết quả như www, thư điện tử,...
- TCP như kiểu 2 hay nhiều người nói chuyện với nhau. Một người  hỏi: "Mày có nghe rõ không" nếu thằng kia trả lời "Có" thì mới thực hiện trò chuyện. Vì vậy TCP đảm bào việc truyền dữ liệu

- Mỗi máy tính có một địa chỉ IP => phân biệt các máy qua địa chỉ IP. Mỗi chương trình trên máy có một cổng kết nối => phân biết các chương trình bằng cổng kết nối. => để gửi dữ liệu cho một chương trình trên máy tính cần có địa chỉ ip của máy và cổng của chương trình đó

- Ngoài TCP thì trong bộ giao thức TCP/IP còn có thêm giao thức UDP. Cái này nó truyền tín hiệu nhanh hơn TCP nhưng tín hiệu truyền đi lại được cho phép mất, không biết thèn kia có nhận được hay chưa. Bù lại thì nó truyền nhanh hơn. Như trong ví dụ 2 thằng nói truyện ở trên, với UDP thì không cần thằng kí trả lời có ta vẫn cứ nói, mặc kệ có nghe tao hay không :D. Giống như kiểu gửi email cho 1 thằng offline, không biết nó có nhận và đọc hay không

- Tài liệu về giao TCP và IP:  https://docs.google.com/document/d/1GR39aiMkP1giKa9Brppbc9loHB2YaQ5QjD0ZX_M2YLo/edit?hl=en

2. System.NET


- Để xây dựng chương trình chat qua mạng LAN ta cần sử dụng: IPEndPoint, Socket, TcpClient, IPAdress

Ở phần tiếp thuvienwinform sẽ mang đến project dành cho máy chủ trong chương trình chat qua mạng LAN.

19-5-2015:
Thực ra với C# có nhiều cách để xây dựng một ứng dụng truyền dữ liệu qua mạng kiểu này. Sử dụng socket là cái nền tảng sơ khai nhất, mình sẽ hướng dẫn một bài khác cũng về vấn đề truyền dữ liệu qua mạng này trên một công nghệ khác (WCF hoặc Remote) đơn giản hơn nhiều, các bạn theo dõi blog để nhận bài sớm nhất nhé!

Thread trong C#

thuvienwinform - Thread cho phép thực hiện cùng lúc nhiều công việc song song với nhau mà không bị đơ, lag (lác :D), gián đoạn. Nó đặc biệt quan trọng trong lập trình mạng, các ứng dụng đỏi hỏi thực hiện công việc nặng nhọc, duyệt vòng lặp lớn (lặp vài trăm nghìn lần như duyệt các thư mục), nếu không dùng thread thì chương trình sẽ không thể tương tác được, có thể rơi vào trạng thái không phản hồi (Not Responding - Cái này quen quen). Nhờ có Thread mà ứng dụng trở nên mượt hơn, hạn chế đơ, lag, sử dụng CPU hiệu quả hơn với lập trình winform.



- Để sử dụng thread ta khai báo using System.Threading;
- Số thread tối đa cho 1 chương trình:
+ Với .NET2.0 là 25.
+ Với .NET3.5 là 250.
+ Với .NET4.0 (32bit) là 1023.
+ Với .NET4.0 (64bit) là 32768.
+...

1/ Tạo thread mới để chạy 1 hàm, thủ tục
- Cho hàm, thủ tục không có tham số truyền vào

Thread t1;
t1 = new Thread(ThuTuc1);
với ThuTuc1 là một thủ tục (void) không có tham số truyền vào

Các ví dụ dưới đây sẽ dùng thread t1 này là ví dụ ạ

- Cho hàm, thủ tục có tham số truyền vào (Sử dụng Lambda Expresstion)

t1 = new Thread();
t1 = new Thread((ThreadStart) =>
    {
        ThuTuc2("Truyen vao");
    });
2/ Chạy thread đó
- Sau khi tọa được thread rùi ta có thể cho nó bắt đầu chạy:

t1.Start();

3/ Dừng thread

t1.Abort();

4/ Tạm dừng thread

t1.Suspend();
Tạm dừng cho đến khi
t1.Resume();


5/ Mức độ ưu tiên của thread (Thread Priority)
- Khi sử dụng nhiều thread thì ta cài đặt độ ưu tiên thực thi của các thread

t1.Priority = ThreadPriority.Lowest;
- Có các giá mức ưu tiên: Lowest, BelowNormal, Normal, AboveNormal, Hightest


6/ Join
- Cái này nó sẽ làm như sau: Những thread dưới câu lệnh Join() sẽ được start sau khi các thread trên câu lệnh join chạy xong

7/ Thoát chương trình nhưng thread vẫn chạy
- Thread có 2 loại: ForeGround và BackGround.
+ Chương trình sẽ tắt khi các ForeGround thread chạy xong
+ Còn các BackGroud Thread sẽ dừng lại khi tắt chương trình.

- Lí do là khi ta tạo 1 thread nó mặc định là loại ForeGround
- Để khi tắt chương trình các thread cũng dừng thì ta sẽ chuyển các thread sang BackGround như sau:

t1.IsBackground = true;
t1.Start();
Chuyển thread thành background trước khi start

8/ Thread Pooling
- Cái này hơn rất rất nhiều. Có thể nói nó tối ưu thread.
- Thread Pooling mặc định là loại BackGround
- Sau khi kết thúc một tác vụ nó sẽ trở về trạng thái sẵn sàng nhận một nhiệm vụ mới
- Chạy một thủ tục, hàm bằng Thread Pooling (thủ tục, hàm phải có đầu vào là 1 Object)

private void Button1_Click()
{
    ThreadPool.QueueUserWorkItem(ThreadPooling, "Test");
   //Hoặc: ThreadPool.QueueUserWorkItem(ThreadPooling);
}
private void ThreadPooling(object obj)
{
    MessageBox.Show(obj.ToString());
}

Nguồn: YinYang's Blog

[ENCODING] Chuyển đổi qua lại giữa các loại mã (Unicode-UTF8-UTF7-ASCII...)

Chào !
Hôm nay mình sẽ hướng dẫn các bạn chuyển đổi các loại mã (Unicode-UTF8-UTF7-ASCII...)
Các bạn có thể hoàn toàn tạo được 1 tool giúp chuyển đổi các loại mã trong Văn bản ^^!
(Ví dụ bạn dùng MS Word đã lỡ dùng Unicode nhưng người ta yêu cầu phải dùng định dạng ASCII hết chẳng hạn ... )

OK. Bắt đầu nhé !
Ở đây mình sẽ ví dụ chuyển mã Unicode sang mã UTF8 :

1. Hãy "using System.Text" để sử dụng lớp Encoding

2. Chuyển dữ liệu về mảng byte :

// Chuyển string szDuLieuUniCode về dạng mảng byte
byte[] unicode = Encoding.Unicode.GetBytes(szDuLieuUniCode);
// Cover byte unicode sang byte utf8
byte[] utf8 = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, unicode);
// chuyển từ mảng byte utf8 về dạng string
string szDuLieuUTF8 = Encoding.UTF8.GetString(utf8);

OK Vậy là đã xong !
4/17/2014
Đăng bởi :
Nhãn :

Nhận ngay 100$ cho VPS

Mua hàng ủng hộ page

Ủng hộ page

Nhãn

Code (45) Team Foundation Server (17) Database (14) News (14) product (13) toolbox (10) Linq (9) SoftDesign (8) XNA (6) API (5) Project (5) item (4)

- Bản quyền thuộc về Thư Viện WinForm - Giao diện: Metrominimalist - Thiết kế: Johanes Djogan -