[C#] Truyền đối tượng qua Socket C#

Hôm trước mình đã hướng dẫn các bạn làm ví dụ đơn giản truyền nhận quan socket trong c#, hôm nay tiếp tục hướng dẫn các bạn truyền đối tượng qua socket 😉

Bài này hướng dẫn các bạn viết chuơng trình truyền nhận đối tượng giữa client và server. Client là 1 From thông tin của 1 cuốn sách (Book) gồm tiêu đề, tác giả, năm xuất bản và thể loại. Client có 2 nút là gửi (sẽ gửi thông tin đến server) và nhận (nhận thông tin từ server). Khi Client ấn nút gửi thì server sẽ nhận thông tin và ghi vào file trên server. Khi Client ấn nút nhận thì server đọc thông tin từ file và gửi xuống Client, Client hiển thị lại thông tin nhận được lên From. Giống như hình dưới đây.

socket trong c#

Bây giờ chún ta sẽ xây dựng 2 Project là BookClient và BookServer có cấu trúc như hình này:

Việc truyền đối tượng qua socket trong c# nó tuơng tự như hôm trước, chỉ có điều chúng ta cần thực hiện chuyển đối tượng về mảng byte sau đó mới gửi nhận được. Khi nhận lại đối tượng thì cần có hàm phục hồi lại đối tượng từ mảng byte đó.

Hàm chuyển 1 đối tượng về mảng byte và ngược lại.

// nen data thanh 1 mang byte
public byte[] SerializeData(Object o)
{
    MemoryStream ms = new MemoryStream();
    BinaryFormatter bf1 = new BinaryFormatter();
    bf1.Serialize(ms, o);
    return ms.ToArray();
}

// giai nen 1 mang byte thanh 1 doi tuong (bject)
public object DeserializeData(byte[] theByteArray)
{
    MemoryStream ms = new MemoryStream(theByteArray);
    BinaryFormatter bf1 = new BinaryFormatter();
    ms.Position = 0;
    return bf1.Deserialize(ms);
}

Tuy nhiên lưu ý các bạn để thực hiện được việc nén đối tượng vào Serialize thì lớp đối tượng đó cần có từ khóa [Serialize] trước class. Cụ thể đối với class Book như sau (class Book nằm trong project của Client)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BookClient
{
    [Serializable]
    class Book
    {
        public String title, author, yearOfPublication, genre;
    }
}

Tiếp theo là code của From Client (Giao diện các bạn tự thiết kế nhé)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;

namespace BookClient
{
    public partial class Form1 : Form
    {
        Socket client;
        private const int BUFFER_SIZE = 1024;
        private const int PORT_NUMBER = 7826;
        static ASCIIEncoding encoding = new ASCIIEncoding();
        public Form1()
        {
            InitializeComponent();
            connectServer();
        }


        // ket noi den server
        private void connectServer()
        {
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), PORT_NUMBER);
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.Connect(iep);
        }


// nen data thanh 1 mang byte
public byte[] SerializeData(Object o)
{
    MemoryStream ms = new MemoryStream();
    BinaryFormatter bf1 = new BinaryFormatter();
    bf1.Serialize(ms, o);
    return ms.ToArray();
}

// giai nen 1 mang byte thanh 1 doi tuong (bject)
public object DeserializeData(byte[] theByteArray)
{
    MemoryStream ms = new MemoryStream(theByteArray);
    BinaryFormatter bf1 = new BinaryFormatter();
    ms.Position = 0;
    return bf1.Deserialize(ms);
}

        // gui du lieu cho server
        private void btnSend_Click(object sender, EventArgs e)
        {
            // tao va lay du lieu tu form
            Book b = new Book();
            b.title = tbTitle.Text;
            b.author = tbAuthor.Text;
            b.yearOfPublication = tbYear.Text;
            b.genre = tbGenre.Text;

            // gui lenh yeu cau la client muon gui du lieu
            client.Send(encoding.GetBytes("send"));

            // gui du lieu
            client.Send(SerializeData(b));
        }

        private void btnReceive_Click(object sender, EventArgs e)
        {
            // gui lenh yeu cau lay du lieu tu server
            client.Send(encoding.GetBytes("receive"));
            byte[] data = new byte[BUFFER_SIZE];

            // nhan du lieu tu server gui xuong
            int rec = client.Receive(data);

            // hien thi thong tin nhan duoc len form
            Book b = (Book)DeserializeData(data);
            tbTitle.Text = b.title;
            tbAuthor.Text = b.author;
            tbYear.Text = b.yearOfPublication;
            tbGenre.Text = b.genre;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

Code của server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Runtime.Serialization.Formatters.Binary;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Text;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
namespace BookServer
{
    class Program
    {
        private const int BUFFER_SIZE = 1024;
        private const int PORT_NUMBER = 7826;

        static ASCIIEncoding encoding = new ASCIIEncoding();
        Socket server;

        // ghi data xuong file
        protected bool SaveData(byte[] Data)
        {
            BinaryWriter Writer = null;
            string Name = "book";

            try
            {
                Writer = new BinaryWriter(File.OpenWrite(Name));          
                Writer.Write(Data);
                Writer.Flush();
                Writer.Close();
            }
            catch
            {
                return false;
            }

            return true;
        }

        private void initServer()
        {
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), PORT_NUMBER);
            // tao server
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Console.WriteLine("dang cho client ket noi...");
            
            // lang nghe ket noi
            server.Bind(iep);
            server.Listen(10);

            // chap nhan client ket noi
            Socket client = server.Accept();
            Console.WriteLine("Chap nhan ket noi tu: " + client.RemoteEndPoint.ToString());
            byte[] data = new byte[BUFFER_SIZE];

            // vong lap vo han thuc hien viec nhan va gui du lieu
            while (true)
            {
                // nhan lenh: gui hoac nhan du lieu
                int rec = client.Receive(data);
                String command = encoding.GetString(data, 0, rec);
                Console.WriteLine("command = " + command);
                
                // client send data den server
                if (command.Equals("send"))
                {
                    client.Receive(data);
                    Console.WriteLine("Nhan thanh cong");
                    if (SaveData(data))
                    {
                        Console.WriteLine("Ghi thanh cong");
                    }
                    else
                    {
                        Console.WriteLine("Ghi that bai");
                    }
                }
                // client muon lay data tu server
                else
                {
                    Console.WriteLine("Dang gui...");
                    // doc du lieu tu file
                    byte[] arraydata = File.ReadAllBytes("book");
                    // gui du lieu doc duoc cho client
                    client.Send(arraydata);
                }
            }
        }

        static void Main(string[] args)
        {
            new Program().initServer();

        }
    }
}

Các bạn có thể download 2 project Client và Server tại đây.