[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.
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.
cho e hỏi là: e có 1 lớp Account từ phía client như sau:
class Account
{
private string username = "";
private string password = "";
public Account(string username, string password)
{
this.username = username;
this.password = password;
}
public string Username{
get
{
return username;
}
}
public string Password
{
get
{
return password;
}
}
}
vậy làm thế nào để server có thể tác được username và password khi mình gửi 1 đối tương Account vậy ạ
Trong bài mình nói rõ rồi mà, bạn cần nén đối tượng đó lại dùng Serialize ấy.
e đã làm r, client đã gửi thành công, nhưng khi sv nhận thì báo lỗi tùm lum. Đây là sv của e:
IPAddress address = IPAddress.Parse("127.0.0.1");
TcpListener listener = new TcpListener(address, PORT_NUMBER);
listener.Start();
Console.WriteLine("Server started on " + listener.LocalEndpoint);
Console.WriteLine("Waiting for a connection...");
Socket socket = listener.AcceptSocket();
Console.WriteLine("Connection received from " + socket.RemoteEndPoint);
byte[] data = new byte[BUFFER_SIZE];
socket.Receive(data);
VO acc = new VO();
acc = BUS.DeserializeData(data);
Console.WriteLine(acc.username + ":" + acc.password);
Class VO tương tự như class Account, chỉ khác tên thôi ạ
Mình có bị lỗi đâu, bạn chạy code của mình xem, cái của bạn thấy cũng ko sao mà
Bạn ơi, làm bài viết hướng dẫn về lập trình mạng đi 😀
Cảm ơn bạn, nhưng mình không theo c# nữa nên rất tiếc ko giúp bạn đk.