سورس کد برنامه تخته سیاه ۲ کاربر شبکه ای در C#/.NET
در دنیای توسعه نرمافزار، برنامههای چندنفره و شبکهای جایگاه ویژهای دارند، مخصوصاً زمانی که نیاز باشد چند کاربر در یک محیط تعاملی به صورت همزمان فعالیت کنند. یکی از نمونههای جذاب و کاربردی این نوع برنامهها، برنامه تخته سیاه است که به کاربران اجازه میدهد در یک فضای مشترک، نقاشی یا یادداشتهای خود را به اشتراک بگذارند و در نتیجه، تعامل و همکاری بهبود یابد. در این مقاله، به طور جامع و کامل به بررسی پیادهسازی یک برنامه تخته سیاه دو کاربره در بستر شبکه با استفاده از زبان برنامهنویسی C# و فریمورک .NET میپردازیم.
در ادامه، ابتدا مفاهیم پایهای و نیازمندیهای اصلی این برنامه را بررسی میکنیم، سپس ساختار کلی آن را شرح میدهیم، و در نهایت، جزئیات فنی و کدهای نمونه را ارائه میدهیم. هدف از این توضیحات، درک کامل فرآیند توسعه، معماری نرمافزار، و نکات مهم در پیادهسازی برنامههای شبکهای است که میتواند برای توسعهدهندگان مبتدی و حرفهای مفید باشد.
مفاهیم پایه و نیازمندیهای برنامه
برنامه تخته سیاه دو کاربره بر پایه معماری کلاینت-سرور ساخته میشود. در این معماری، یک کامپیوتر نقش سرور را ایفا میکند که مسئول مدیریت ارتباطات و تبادل دادهها است، و دو دستگاه دیگر، نقش کلاینتها را دارند که وظیفه نمایش و دریافت دادههای تصویری و تعاملی را بر عهده دارند. این پروژه نیازمند پیادهسازی موارد زیر است:
- ارتباط شبکهای: استفاده از پروتکل TCP/IP برای برقراری ارتباط پایدار و مطمئن بین سرور و کلاینتها.
- رابط گرافیکی کاربر (GUI): طراحی محیطی ساده و کاربرپسند که کاربران بتوانند در آن نقاشی کنند، خطوط، اشکال، یا متنهای دلخواه را بکشند.
- همزمانی و همزمانسازی: اطمینان حاصل شود که تمامی تغییرات و نقاشیهای انجامشده توسط هر کاربر، در لحظه روی صفحه کاربر دیگر نیز ظاهر میشود.
- مدیریت چند کاربر: در حالت ساده، دو کاربر، ولی با قابلیت توسعه به چند کاربر در آینده.
- پایداری و امنیت ارتباطات: اطمینان از این که دادهها بدون خطا و به صورت امن منتقل میشوند، و ارتباطات قطع نمیشوند یا از بین نمیروند.
با در نظر گرفتن این نیازمندیها، ساختار کلی پروژه شامل دو بخش اصلی است: سرور و کلاینتها. سرور، نقش مرکزی را ایفا میکند و تمامی دادههای تصویری و دستورهای نقاشی را مدیریت، دریافت، و توزیع مینماید. کلاینتها، رابط کاربری را ارائه میدهند و دادهها را به سرور ارسال و دریافت میکنند.
ساختار کلی و معماری برنامه
برای پیادهسازی این پروژه، معماری چند لایه و ماژولار بسیار مناسب است. معماری کلی به صورت زیر است:
1. ماژول سرور:
- مدیریت اتصالهای کلاینتها.
- دریافت دادههای تصویری یا دستورات نقاشی.
- توزیع دادههای دریافتی به کلاینتهای دیگر.
- کنترل وضعیت اتصال و مدیریت خطاها.
2. ماژول کلاینت:
- رابط کاربری گرافیکی.
- ارسال دستورات و نقاشیها به سرور.
- دریافت دادههای تصویری از سرور و بروزرسانی صفحه نمایش.
3. ماژول شبکه:
- پیادهسازی ارتباط TCP/IP.
- مدیریت سوکتها و پروتکلهای ارتباطی.
- رمزگذاری و رمزگشایی دادهها در صورت نیاز.
4. ماژول تصویری و UI:
- ابزارهای نقاشی شامل قلم، رنگ، اشکال هندسی.
- رویدادهای واکنشگرا برای ثبت حرکتهای ماوس و کلیدهای صفحه کلید.
- بروزرسانی صفحه به صورت همزمان.
در ادامه، به طور جزئیتر، به پیادهسازی هر بخش میپردازیم و نمونه کدهای پایه را ارائه میدهیم.
پروتکل و تبادل دادهها
در برنامه تخته سیاه، مهمترین بخش، نحوه انتقال دادههای تصویری است. معمولا، هر نقاشی یا خط کشیده شده، به صورت مجموعهای از نقاط، رنگ، ضخامت قلم، و دستورهای مربوطه به سرور ارسال میشود. سرور، این دادهها را دریافت و به سایر کلاینتها توزیع میکند، بنابراین هر کاربر، صفحهای همسان و بهروز دارد.
برای سادهسازی، میتوانیم از قالبهای JSON یا Binary برای کدگذاری دادهها استفاده کنیم. در نمونههای اولیه، JSON گزینهای ساده و قابل فهم است. به عنوان نمونه، یک داده نقاشی ممکن است به صورت زیر باشد:
json
{
"type": "drawLine",
"startX": 10,
"startY": 20,
"endX": 100,
"endY": 200,
"color": "#FF0000",
"thickness": 2
}
سرور، این پیامها را دریافت میکند و به کلاینت دیگر ارسال مینماید، که در نتیجه، هر کاربر حرکت موس و کشیدن خطهای دیگر را در لحظه مشاهده میکند.
کد نمونه سرور در C#
در نمونه زیر، سرور به صورت ساده پیادهسازی شده است که چند کلاینت را مدیریت میکند و دادههای نقاشی را رد و بدل مینماید:
csharp
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
class DrawingServer
{
private TcpListener listener;
private List<TcpClient> clients = new List<TcpClient>();
public async Task StartAsync(int port)
{
listener = new TcpListener(IPAddress.Any, port);
listener.Start();
Console.WriteLine("Server started...");
while (true)
{
var client = await listener.AcceptTcpClientAsync();
clients.Add(client);
_ = HandleClientAsync(client);
}
}
private async Task HandleClientAsync(TcpClient client)
{
var stream = client.GetStream();
byte[] buffer = new byte[4096];
try
{
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break; // disconnected
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
BroadcastMessage(message, client);
}
}
catch
{
// Handle exceptions
}
finally
{
clients.Remove(client);
client.Close();
}
}
private void BroadcastMessage(string message, TcpClient excludeClient)
{
byte[] data = Encoding.UTF8.GetBytes(message);
foreach (var client in clients)
{
if (client != excludeClient)
{
var stream = client.GetStream();
stream.WriteAsync(data, 0, data.Length);
}
}
}
}
این نمونه، یک سرور ساده است که هر پیام دریافتشده را به سایر کلاینتها میفرستد. در پروژه واقعی، باید خطاها، مدیریت اتصال، و امنیت را نیز لحاظ کنید.
کد نمونه کلاینت در C#
کلاینت باید قابلیت رسم بر روی صفحه و ارسال دادههای نقاشی به سرور را داشته باشد. در اینجا، نمونه کد پایه برای کلاینت است:
csharp
using System;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Threading.Tasks;
public class DrawingClient : Form
{
private TcpClient client;
private NetworkStream stream;
private Point startPoint, endPoint;
private bool isDrawing = false;
public DrawingClient()
{
this.Text = "شبکهای تخته سیاه";
this.Size = new Size(800, 600);
this.MouseDown += MouseDownHandler;
this.MouseMove += MouseMoveHandler;
this.MouseUp += MouseUpHandler;
ConnectToServer();
}
private async void ConnectToServer()
{
client = new TcpClient();
await client.ConnectAsync("127.0.0.1", 5000);
stream = client.GetStream();
_ = ReceiveDataAsync();
}
private async Task ReceiveDataAsync()
{
byte[] buffer = new byte[4096];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0) break;
string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// پردازش پیام و رسم در صفحه
}
}
private void MouseDownHandler(object sender, MouseEventArgs e)
{
isDrawing = true;
startPoint = e.Location;
}
private async void MouseUpHandler(object sender, MouseEventArgs e)
{
if (isDrawing)
{
endPoint = e.Location;
isDrawing = false;
// رسم خط روی صفحه
this.Invalidate();
// ارسال داده به سرور
var jsonData = $"{{\"type\":\"drawLine\",\"startX\":{startPoint.X},\"startY\":{startPoint.Y},\"endX\":{endPoint.X},\"endY\":{endPoint.Y},\"color\":\"#000000\",\"thickness\":2}}";
byte[] data = Encoding.UTF8.GetBytes(jsonData);
await stream.WriteAsync(data, 0, data.Length);
}
}
private void MouseMoveHandler(object sender, MouseEventArgs e)
{
if (isDrawing)
{
endPoint = e.Location;
// موقتاً، میتوان برای نمایش زود هنگام خط کشیده شده، صفحه را بروز کرد
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (isDrawing)
{
e.Graphics.DrawLine(Pens.Black, startPoint, endPoint);
}
}
[STAThread]
static void Main()
{
Application.Run(new DrawingClient());
}
}
در این نمونه، کلاینت قابلیت اتصال به سرور، رسم خط در زمان حرکت موس، و ارسال دادههای نقاشی را دارد. برای کاملتر کردن پروژه، باید بخش دریافت دادههای سرور و رسم آنها به صورت زنده بر روی صفحه اضافه شود.
جمعبندی و نکات مهم
در این مقاله، سعی شد که تمامی مراحل ساخت برنامه تخته سیاه دو کاربره در شبکه با C#/.NET به صورت جامع و دقیق توضیح داده شود. از مفاهیم پایه، معماری، پروتکلهای ارتباطی، تا نمونه کدهای عملی و کاربردی. نکته مهم، تمرکز بر همزمانی و همزمانسازی است، تا تجربه کاربری روان و بدون تأخیر فراهم شود.
در ادامه، توسعهدهندگان میتوانند این پروژه را گسترش دهند، به عنوان مثال، اضافه کردن قابلیتهای رنگهای مختلف، اشکال هندسی، قابلیت ذخیرهسازی نقاشیها، و حتی پشتیبانی چندنفره بیشتر را پیادهسازی کنند. همچنین، برای افزایش امنیت، میتوان از روشهای رمزگذاری دادهها و مدیریت کاربران بهره برد.
در پایان، توسعه نرمافزارهای شبکهای، به خصوص برنامههای تعاملی و تصویری، نیازمند دانش عمیق در زمینه شبکه، برنامهنویسی گرافیکی، و معماری نرمافزار است. ولی با تمرین و مطالعه مداوم، میتوان به ساخت برنامههایی جذاب و کارآمد دست یافت که نه تنها ابزار آموزشی بلکه فرصتهای خلاقیت و همکاری را برای کاربران فراهم میکنند.