# برنامه نویسی با محصولات مایکروسافت > برنامه نویسی مبتنی بر Microsoft .Net Framework > WCF , Web Services , .Net Remoting >  ساخت برنامه کلاینت سروری

## Payman62

سلام.
برای نوشتن برنامه کلاینت سروری باید چه کامپوننتی رو اضافه کنم؟
تو ویبی وینساک بود ولی تو  2005   C#‎ پیداش نکردم.
کلا روش نوشتن برنامه کلاینت سروری رو تو C#‎ اگه میشه توضیح بدید. اینکه چه تابع هایی باید بنویسم یا از چه ایونت هایی استفاده کنم.
سرچ کردم به این نتیجه رسیدم که از System.Net.Sockets استفاده کنم. ولی توضیح در مورد روش کار میخوام.
ممنون میشم کمکم کنید.

----------


## Payman62

سلام.
کسی جواب نمیده؟

----------


## Payman62

سلام.
خواهشا راهنمایی کنید. یعنی هیچ کس بلد نیست؟

----------


## mohy_heidari

سلام دوست عزیز

برای ساختن این نوع برنامه ها نیاز به یک سری اطلاعات در مورد معماری شبکه های کامپیوتری داری ولی من فرض رو بر این میبینم که شما از شبکه سر در میارین :

در برنامه نویسی شبکه به صورت ساده میتونید از دو نوع پروتکل برای ارتباط استفاده کنید 

Tcp , Udp

برای برنامه نویسی در پروتکل Tcp :

اول یک IPEndPoint تعریف میکنید. این کلاس برای وارد کردن IP , Port به کار میره :

بعد یک Socket ایجاد میکنید. این کلاس برای ارتباط با سرور یا قبول ارتباط از سمت کلاینت به کار میره.

این هم یک نمونه برنامه خیلی ساده برای سمت سرور :


using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
classSimpleTcpSrvr
{
publicstaticvoid Main()
{
int recv;
byte[] data = newbyte[1024];
IPEndPoint ipep = newIPEndPoint(IPAddress.Any,
9050);
Socket newsock = new
Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Console.WriteLine("Waiting for a client...");
Socket client = newsock.Accept();
IPEndPoint clientep =
(IPEndPoint)client.RemoteEndPoint;
Console.WriteLine("Connected with {0} at port {1}",
clientep.Address, clientep.Port);
string welcome = "Welcome to my test server";
data = Encoding.ASCII.GetBytes(welcome);
client.Send(data, data.Length,
SocketFlags.None);
while (true)
{
data = newbyte[1024];
recv = client.Receive(data);
if (recv == 0)
break;
Console.WriteLine(
Encoding.ASCII.GetString(data, 0, recv));
client.Send(data, recv, SocketFlags.None);
}
Console.WriteLine("Disconnected from {0}",
clientep.Address);
client.Close();
newsock.Close();
}
}


این هم یک نمونه برنامه سمت Client :


using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
classSimpleTcpClient
{
publicstaticvoid Main()
{
byte[] data = newbyte[1024];
string input, stringData;
IPEndPoint ipep = newIPEndPoint(
IPAddress.Parse("127.0.0.1"), 9050);
Socket server = newSocket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
try
{
server.Connect(ipep);
}
catch (SocketException e)
{
Console.WriteLine("Unable to connect to server.");
Console.WriteLine(e.ToString());
return;
}
int recv = server.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
while (true)
{
input = Console.ReadLine();
if (input == "exit")
break;
server.Send(Encoding.ASCII.GetBytes(input));
data = newbyte[1024];
recv = server.Receive(data);
stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine(stringData);
}
Console.WriteLine("Disconnecting from server...");
server.Shutdown(SocketShutdown.Both);
server.Close();
}
}


این دو تا برنامه رو اگه همزمان اجرا کنی یک برنامه خیلی ساده برای چت میشه.

----------


## hassan razavi

یک نمونه برنامه در لینک زیر هست :
https://barnamenevis.org/showth...419#post427419

----------


## combo_ci

اگر منظورت از کلاینت سرور اینه که برنامت بتونه روی یه سرور اطلاعات خودش رو ذخیره کنه اصلا لازم به نوشتن نسخه سرور نیست چون sql server همه این کارها رو انجام میده 
من خودم واسه یه کارخونه که چند تا زیر مجموعه داشت یه همچین برنامه نوشتم که زیر مجموعه ها اطلاعات خودشون رو روی sql server میریزن (البته با نسخه محدود شده client) سرور هم از sql server اطلاعات کلاینت ها رو با نسخه کاملتر برنامه دریافت میکنه...این کار فکر میکنم راحتر باشه

----------


## Payman62

سلام.
جناب mohy_heidari کدی که قرار دادی به خوبی کار میکنه. من کد رو به برنامه فرمی برگردوندم. ولی یه مشکلی که هست client.recive باعث قفل شدن فرم میشه. چه تابعی هست که هر وقت داده ای از طرف مقابل ارسال شد اتوماتیک صدا زده بشه و اطلاعات رو دریافت کنه؟

----------


## afsar

سلام 
یه سوال دارم که شاید زیاد به این قسمت مربوط نباشه

آیا می شود Server Application از نوع #C ولی Client Application آن از نوع ++C باشد؟

لطفا راهنمایی نمایید...

با تشکر

----------


## mohy_heidari

> سلام.
> جناب mohy_heidari کدی که قرار دادی به خوبی کار میکنه. من کد رو به برنامه فرمی برگردوندم. ولی یه مشکلی که هست client.recive باعث قفل شدن فرم میشه. چه تابعی هست که هر وقت داده ای از طرف مقابل ارسال شد اتوماتیک صدا زده بشه و اطلاعات رو دریافت کنه؟


راه حل این مسئله رو دو جور میشه حل کرد 

اول اینکه از Thread ها استفاده کنید. 
دوم اینکه از تابع ReciveAsync استفاده کنید 

در حالت اول دو روش برای استفاده از Thread وجود داره :

یکی اینکه از کامپوننتی که به اسم BackGroundWorker هست استفاده کنید که همین کار رو پیشنهاد میکنم 
حالت دوم هم ایجاد یک Thread به صورت دستی هست که کمی پیچیدگی داره به همین دلیل استفاده از BackGroundWorker رو توضیح میدم :

این کامپوننت هم نوعی Thread هست با این تفاوت که دیگه نیازی به Delegate و تعریف و پیچیدگی وجود نداره و شما با اضافه کردن به فرم خودتون میتونین به سادگی ازش استفاده کنید.

روش کار اینطوری هست که به عنوان مثال یک فرم ایجاد کنید و این کامپوننت رو از ToolBox بر روی فرم میندازین و تو رویداد DoWork این کامپوننت کاری رو که میخواین انجام بدین رو مینویسین و وقتی که میخواید اون کار رو اجرا کنید متد RunWorkAsync این کامپوننت رو فرا خوانی میکنید.

روش دیگه ای هم که وجود داشت استفاده از ReciveAsync تو شئ Socket هست که اونهم در واقع همین کار رو به روشی دیگه انجام میده که نیاز به توضیح نمیبینم ولی اگه خواستین بیشتر توضیح میدم.


در رابطه با اطلاع داشتن از زمان دریافت اطلاعات شما باید این کار رو بکنید که مقدار بازگشتی متد Recive رو تست کنید :


int test = sock.Receive(data);
if (test == 0) 
//داده ای وجود ندارد
else
{
//داده ای در بافر وجود دارد و طول داده برابر مقدار میباشد
}
برای اینکه بتونید هر لحظه این مقدار رو تست کنید باید از یک حلقه و یا Thread استفاده کنید.

موفق باشید. :لبخند: 




> سلام 
> یه سوال دارم که شاید زیاد به این قسمت مربوط نباشه
> 
> آیا می شود Server Application از نوع #C ولی Client Application آن از نوع ++C باشد؟
> 
> لطفا راهنمایی نمایید...
> 
> با تشکر


بله برنامه های کلاینت / سرور کاری به زبان یا محیط اجرایی ندارن و فقط با Protocol شبکه کار دارن و ارسال و دریافت داده ها.

به عنوان مثال سایت barnamenevis.org بر روی یک سرور Linux قرار داره و شما هم احتمالا از سیستم عامل Windows استفاده میکنید. پس میبینید که ربطی به نوع سیستم یا زبان برنامه نویسی نداره و ارتباط برقرار میشه.

موفق باشید.

----------


## Payman62

سلام.
ترجیح میدم به جای استفاده از کامپوننت از دستورات خود C#‎ استفاده کنم تا یاد بگیرم.
میشه بیشتر توضیح بدی.

----------


## afsar

سلام

من توی #C و ++C هر کدام جداگانه جواب گرفته ام. 
ولی وقتی Client و Server متفاوت می شوند دیگه جواب نمی ده!!!

اگه شما نمونه ای یا راهنمایی ای دارید که بتونه کمک کنه ممنون می شم برام بفرستید.

با تشکر

----------


## mohy_heidari

> سلام.
> ترجیح میدم به جای استفاده از کامپوننت از دستورات خود C#‎ استفاده کنم تا یاد بگیرم.
> میشه بیشتر توضیح بدی.


 
این کد رو تو قسمت Client تست کن.


using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
classAsyncTcpClient : Form
{
privateTextBox newText;
privateTextBox conStatus;
privateListBox results;
privateSocket client;
privatebyte[] data = newbyte[1024];
privateint size = 1024;
public AsyncTcpClient()
{
Text = "Asynchronous TCP Client";
Size = newSize(400, 380);
Label label1 = newLabel();
label1.Parent = this;
label1.Text = "Enter text string:";
label1.AutoSize = true;
label1.Location = newPoint(10, 30);
newText = newTextBox();
newText.Parent = this;
newText.Size = newSize(200, 2 * Font.Height);
newText.Location = newPoint(10, 55);
results = newListBox();
results.Parent = this;
results.Location = newPoint(10, 85);
results.Size = newSize(360, 18 * Font.Height);
Label label2 = newLabel();
label2.Parent = this;
label2.Text = "Connection Status:";
label2.AutoSize = true;
label2.Location = newPoint(10, 330);
conStatus = newTextBox();
conStatus.Parent = this;
conStatus.Text = "Disconnected";
conStatus.Size = newSize(200, 2 * Font.Height);
conStatus.Location = newPoint(110, 325);
Button sendit = newButton();
sendit.Parent = this;
sendit.Text = "Send";
sendit.Location = newPoint(220, 52);
sendit.Size = newSize(5 * Font.Height, 2 * Font.Height);
sendit.Click += newEventHandler(ButtonSendOnClick);
Button connect = newButton();
connect.Parent = this;
connect.Text = "Connect";
connect.Location = newPoint(295, 20);
connect.Size = newSize(6 * Font.Height, 2 * Font.Height);
connect.Click += newEventHandler(ButtonConnectOnClick);
Button discon = newButton();
discon.Parent = this;
discon.Text = "Disconnect";
discon.Location = newPoint(295, 52);
discon.Size = newSize(6 * Font.Height, 2 * Font.Height);
discon.Click += newEventHandler(ButtonDisconOnClick);
}
void ButtonConnectOnClick(object obj, EventArgs ea)
{
conStatus.Text = "Connecting...";
Socket newsock = newSocket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = newIPEndPoint(IPAddress.Parse("127.0.0.1"), 5050);
newsock.BeginConnect(iep, newAsyncCallback(Connected), newsock);
}
void ButtonSendOnClick(object obj, EventArgs ea)
{
byte[] message = Encoding.ASCII.GetBytes(newText.Text);
newText.Clear();
client.BeginSend(message, 0, message.Length, SocketFlags.None,
newAsyncCallback(SendData), client);
}
void ButtonDisconOnClick(object obj, EventArgs ea)
{
client.Close();
conStatus.Text = "Disconnected";
}
void Connected(IAsyncResult iar)
{
client = (Socket)iar.AsyncState;
try
{
client.EndConnect(iar);
conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
client.BeginReceive(data, 0, size, SocketFlags.None,
newAsyncCallback(ReceiveData), client);
}
catch (SocketException)
{
conStatus.Text = "Error connecting";
}
}
void ReceiveData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int recv = remote.EndReceive(iar);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
results.Items.Add(stringData);
}
void SendData(IAsyncResult iar)
{
Socket remote = (Socket)iar.AsyncState;
int sent = remote.EndSend(iar);
remote.BeginReceive(data, 0, size, SocketFlags.None,
newAsyncCallback(ReceiveData), remote);
}
publicstaticvoid Main()
{
Application.Run(newAsyncTcpClient());
}
}

----------


## mohy_heidari

> سلام
> 
> من توی #C و ++C هر کدام جداگانه جواب گرفته ام. 
> ولی وقتی Client و Server متفاوت می شوند دیگه جواب نمی ده!!!
> 
> اگه شما نمونه ای یا راهنمایی ای دارید که بتونه کمک کنه ممنون می شم برام بفرستید.
> 
> با تشکر


منظورتون C++‎ Win32 هست یا C++‎.Net ؟

اگه منظورتون C++‎.Net باشه که در صورتی که خطای منطقی نداشته باشه کار میکنه

ولی اگه منظور شما Win32 هست باید هر دو سمت به نوعی قرینه همدیگه باشن مثلا از پورتی که رو سرور برای Listining و یا Send , Receive استفاده میشه تو سمت کلاینت هم از همان پورت استفاده بشه. البته این قضیه مربوط به زبان مورد استفاده نیست اما باید دقت بشه.

بنده خودم تو یک پروژه که سمت سرور رو باید من مینوشتم از C#‎.Net استفاده کردم و سمت کلاینت رو که یکی از همکارای بنده کار کرده بودن با زبان Java نوشته بود و بدون هیچ مشکلی کار میکرد.

----------


## Payman62

سلام.
جناب حیدری این کد برای کلاینت به خوبی جواب میده ولی سرور چی؟ لیسن نداره کدت.

----------


## Payman62

سلام.
چی شد پس؟

----------


## mohy_heidari

> سلام.
> جناب حیدری این کد برای کلاینت به خوبی جواب میده ولی سرور چی؟ لیسن نداره کدت.


سلام برنامه ای که گذاشتم برای سمت کلاینت هست و با همون برنامه قبلی هم به خوبی کار میکنه.

شما اگه بگید که دقیقا میخواید چی کار کنید من بهتر میتونم کمک کنم. 
میخواید چه برنامه ای بنویسید.

----------


## Payman62

> سلام برنامه ای که گذاشتم برای سمت کلاینت هست و با همون برنامه قبلی هم به خوبی کار میکنه.
> 
> شما اگه بگید که دقیقا میخواید چی کار کنید من بهتر میتونم کمک کنم. 
> میخواید چه برنامه ای بنویسید.


سلام.
من نگفتم با برنامه قبلی کار نمیکنه. گفتم میخوام کد سرور رو هم با روش Asynchronous بنویسم.
کد قبلی از روش Synchronous استفاده کرده بود که کار کردن با این روش رو یاد گرفتم. حالا میخوام کار کردن با Asynchronous رو یاد بگیرم. کد کلاینتشو شما گذاشتی. کد سرورش رو هم لطف کن.

----------


## Payman62

سلام.
کس نمیتونه راهنمایی کنه؟

----------


## mohy_heidari

این هم سمت کلاینت :
اگه در مورد خاصی تو این کد مشکلی داشتین حتما بپرسین راهنمایی میکنم  :قلب: 


using System;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
classAsyncTcpSrvr : Form
{
private TextBox conStatus;
private ListBox results;
privatebyte[] data = newbyte[1024];
privateint size = 1024;
privateSocket server;
public AsyncTcpSrvr()
{
Text = "Asynchronous TCP Server";
Size = new Size(400, 380);
results = new ListBox();
results.Parent = this;
results.Location = new Point(10, 65);
results.Size = new Size(350, 20 * Font.Height);
Label label1 = new Label();
label1.Parent = this;
label1.Text = "Text received from client:";
label1.AutoSize = true;
label1.Location = new Point(10, 45);
Label label2 = new Label();
label2.Parent = this;
label2.Text = "Connection Status:";
label2.AutoSize = true;
label2.Location = new Point(10, 330);
conStatus = new TextBox();
conStatus.Parent = this;
conStatus.Text = "Waiting for client...";
conStatus.Size = new Size(200, 2 * Font.Height);
conStatus.Location = new Point(110, 325);
Button stopServer = new Button();
stopServer.Parent = this;
stopServer.Text = "Stop Server";
stopServer.Location = new Point(260, 32);
stopServer.Size = new Size(7 * Font.Height, 2 * Font.Height);
stopServer.Click += newEventHandler(ButtonStopOnClick);
server = newSocket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
IPEndPoint iep = newIPEndPoint(IPAddress.Any, 9050);
server.Bind(iep);
server.Listen(5);
server.BeginAccept(newAsyncCallback(AcceptConn), server);
}
void ButtonStopOnClick(object obj, EventArgs ea)
{
Close();
}
void AcceptConn(IAsyncResult iar)
{
Socket oldserver = (Socket)iar.AsyncState;
Socket client = oldserver.EndAccept(iar);
conStatus.Text = "Connected to: " + client.RemoteEndPoint.ToString();
string stringData = "Welcome to my server";
byte[] message1 = Encoding.ASCII.GetBytes(stringData);
client.BeginSend(message1, 0, message1.Length, SocketFlags.None,
newAsyncCallback(SendData), client);
}
void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
client.BeginReceive(data, 0, size, SocketFlags.None,
newAsyncCallback(ReceiveData), client);
}
void ReceiveData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int recv = client.EndReceive(iar);
if (recv == 0)
{
client.Close();
conStatus.Text = "Waiting for client...";
server.BeginAccept(newAsyncCallback(AcceptConn), server);
return;
}
string receivedData = Encoding.ASCII.GetString(data, 0, recv);
results.Items.Add(receivedData);
byte[] message2 = Encoding.ASCII.GetBytes(receivedData);
client.BeginSend(message2, 0, message2.Length, SocketFlags.None,
newAsyncCallback(SendData), client);
}
publicstaticvoid Main()
{
Application.Run(newAsyncTcpSrvr());
}
}

----------


## Payman62

سلام.
جناب حیدری کدت به خوبی کار میکنه.
فقط یه مشکل کوچیک هست. وقتی یه طرف disconnect میشه طرف دیگه Error میده و برنامه بسته میشه. چطور میتونم dc شدن رو کنترل کنم که طرف مقابل به مشکل بر نخوره؟

----------


## mohy_heidari

> سلام.
> جناب حیدری کدت به خوبی کار میکنه.
> فقط یه مشکل کوچیک هست. وقتی یه طرف disconnect میشه طرف دیگه Error میده و برنامه بسته میشه. چطور میتونم dc شدن رو کنترل کنم که طرف مقابل به مشکل بر نخوره؟


با عرض پوزش از مشکل کد :
برای حل این مشکل یک شرط کوچک سمت سرور تو متد SendData باید اضافه کنید. 

این کد مشکل دار هست :


void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
client.BeginReceive(data, 0, size, SocketFlags.None,
newAsyncCallback(ReceiveData), client);
}


کد اصلاح شده :


void SendData(IAsyncResult iar)
{
Socket client = (Socket)iar.AsyncState;
int sent = client.EndSend(iar);
if (!client.Blocking)
client.BeginReceive(data, 0, size, SocketFlags.None,
newAsyncCallback(ReceiveData), client);
}


هدف از این کد این هست که اگه کلاینت در حالت بلوکه نباشد عملیات دریافت را انجام بده

----------


## Payman62

سلام.
این کد روی سیستم من جواب نداد. client.Blocking در حالت عادی تورو هست.

یه سوال دیگه هم بپرسم. فرض کنیم چند تا کامپیوتر در شبکه فایل سرور روشون اجرا شده. یه کلاینت باید اسکن کنه و به تک تک سرور ها وصل شه و اطلاعاتی بگیره. چه راهی رو پیشنهاد میکنید. متغیر که از نوع SOCKET هست رو به صورت آرایه تعریف کنم؟ روش کار چه جوریه؟

سلام.
جناب حیدری رو سیستم من client.Blocking چه کانکت باشم چه نباشم تورو هست. ولی client.Connected بعد از کانکت شدن تورو هست و هنگامی که دیسکانکت میشم فالس میشه.
من از این خاصیت به جای Blocking استفاده کردم. ولی بازم وقتی dc میکنم یه طرف رو طرف دیگه ارور میده. چون قبل از dc کردن آماده دریافت اطلاعات شده و وقتی dc میکنم ارور میده.
فکر میکنم قبل dc کردن باید به طرف مقابل اطلاع بدم و کاری کنم که آمادگی dc شدن رو داشته باشه. مثلا client.EndReceive میتونه بهم کمک کنه؟

سلام.
من  این کد رو  برای دیسکانکت کردن نوشتم. ولی ارور میده. میشه اصلاحش کنید.
        private void ButtonDisconOnClick_Click(object sender, EventArgs e)
        {
            Connection.BeginDisconnect(true, new AsyncCallback(Disconnect), Connection);
        }

        private void Disconnect(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            remote.EndDisconnect(iar);
            Connection.Close();
            conStatus.Text = "Disconnected";
        }
Connection یه متغیره که در سطح کلاس تعریف شده.

سلام.
به نظر میاد تو این فروم غیر از آقای حیدری دیگه کسی شبکه کار نیست. فقط ایشون جواب سوال های منو میدن.

سلام.
من عجله دارم. خواهش میکنم راهنمایی کنید.

سلام.
یکی راهنمایی کنه. یه دسکانکت کردن دو تا برنامه کلاینت سروری که با روش Asynchronous  به هم وصل شده اند این قدر مشکله؟

سلام.
من هنوز منتظرم.

کارم گیره. جواب بدید.

یکی راهنمایی کنه.

من منتظرم.

----------


## Payman62

سلام.
یکی راهنمایی کنه.

----------


## Payman62

یکی جواب منو بده.

----------


## TAK_C#‎Programmer

سلام    
من برنامه چت نوشتم،وازbackgronung برای listen استفاده کردم(در رویداد form_load).برنامه اول listen میکنه و برنامه دوم یک پیام میفرسته، ولی وقتی برنامه اول پیام را دریافت کرد،چی کار کنم تا دوباره listen کنه؟ چطوری ؟ نمتونم دوباره backgroundworker را اجرا کنم !
میخوام برنامه اول به محض دریافت یک پیام دوباره listen کنه و این کار تکرار بشه.
  ممنون از راهنمایی شما دوستان

----------


## qMohammad.fp

> سلام دوست عزیز
> 
> برای ساختن این نوع برنامه ها نیاز به یک سری اطلاعات در مورد معماری شبکه های کامپیوتری داری ولی من فرض رو بر این میبینم که شما از شبکه سر در میارین :
> 
> در برنامه نویسی شبکه به صورت ساده میتونید از دو نوع پروتکل برای ارتباط استفاده کنید 
> 
> Tcp , Udp
> 
> برای برنامه نویسی در پروتکل Tcp :
> ...


*
سلام، لطفا مرحله به مرحله این کدهارو توضیح بدید.
چطور باید کدنویسی کرد که از طریق سرور هم پاسخ بدیم(از طریق کیبورد)*

----------

