PDA

View Full Version : C# TCP Server



Sharpist
سه شنبه 28 اردیبهشت 1389, 19:08 عصر
من در حال یادگیری سی شارپ هستم.
دوست ندارم از روی کتاب کار کنم و میخوام به نیاز هایم برسم و برنامه های واقعی بنویسم.
من نیاز به یک برنامه ی سرور TCP دارم که روی یک پورت listen کنه. و به client ها به صورت همزمان و multithread جواب بده.

چندین سورس مختلف رو تست کردم، اما هیچ کدوم به صورت multi thread نبود.

یک نمونه در ادامه مثال میزنم که اگه به صورت multi thread در بیارید عالی میشه:


namespace CSServer
{
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;


class CSServer
{

private TcpListener myListener;
private string ip = "127.0.0.1";
private int port = 81;


// Application Starts Here..
public static void Main()
{
CSServer MWS = new CSServer();
}


//The constructor which make the TcpListener start listening on the
//given port. It also calls a Thread on the method StartListen().
public CSServer()
{
try
{
//start listing on the given port
myListener = new TcpListener(IPAddress.Parse(ip), port);
myListener.Start();
Console.WriteLine("Web Server Running... Press ^C to Stop...");
//start the thread which calls the method 'StartListen'
Thread th = new Thread(new ThreadStart(StartListen));
th.Start();
}
catch (Exception e)
{
Console.WriteLine("An Exception Occurred while Listening :" + e.ToString());
}
}





/// <summary>
/// Overloaded Function, takes string, convert to bytes and calls
/// overloaded sendToBrowserFunction.
/// </summary>
/// <param name="sData">The data to be sent to the browser(client)</param>
/// <param name="mySocket">Socket reference</param>
public void SendToBrowser(String sData, ref Socket mySocket)
{
SendToBrowser(Encoding.ASCII.GetBytes(sData), ref mySocket);
}



/// <summary>
/// Sends data to the browser (client)
/// </summary>
/// <param name="bSendData">Byte Array</param>
/// <param name="mySocket">Socket reference</param>
public void SendToBrowser(Byte[] bSendData, ref Socket mySocket)
{
int numBytes = 0;

try
{
if (mySocket.Connected)
{
if ((numBytes = mySocket.Send(bSendData, bSendData.Length, 0)) == -1)
Console.WriteLine("Socket Error cannot Send Packet");
else
{
Console.WriteLine("No. of bytes send {0}", numBytes);
}
}
else
Console.WriteLine("Connection Dropped....");
}
catch (Exception e)
{
Console.WriteLine("Error Occurred : {0} ", e);

}
}



//This method Accepts new connection and
//First it receives the welcome massage from the client,
//Then it sends the Current date time to the Client.
public void StartListen()
{
while (true)
{
//Accept a new connection
Socket mySocket = myListener.AcceptSocket();

Console.WriteLine("Socket Type " + mySocket.SocketType);
if (mySocket.Connected)
{
Console.WriteLine("\nClient Connected!!\n==================\nCLient IP {0}\n",
mySocket.RemoteEndPoint);



//make a byte array and receive data from the client
Byte[] bReceive = new Byte[1024];
int i = mySocket.Receive(bReceive, bReceive.Length, 0);



//Convert Byte to String
string sBuffer = Encoding.ASCII.GetString(bReceive);

SendToBrowser("This is", ref mySocket);
Thread.Sleep(5000);
SendToBrowser(" a test!", ref mySocket);

mySocket.Close();
}
}
}
}
}

Open-Source
سه شنبه 28 اردیبهشت 1389, 21:04 عصر
اینجا یه برنامه چت ساده هستش که از Thread استفاده کرده ولی MultiUser نیست (با پیدا کردن یک کلاینت دست از listen میکشه) و باید خودت زحمتش رو بکشی.

http://open-source.blogfa.com/post-39.aspx

Sharpist
سه شنبه 28 اردیبهشت 1389, 22:49 عصر
مشکل من هم دقیقا همینه:
چطور همزمان درخواست چند کلاینت رو پردازش کنیم؟
یعنی یک کلاینت منتظر نمونه تا زمانی که کلاینت های قبلی کارشون تموم بشه و سرور همزمان به درخواست ها جواب بده.

bpzone
چهارشنبه 29 اردیبهشت 1389, 08:27 صبح
با سلام
به برنامه زیر یه نگاهی بنداز و ببین کارت راه می افته ؟
یک برنامه هست بصورت کلاینت سرور
برنامه
Multithread
هست
کلاینت ها یک سری عبارت ریاضی به سرور ارسال می کنن و سرور عبارت رو محاسبه و جواب رو به کلاینت مربوطه برمی گردونه
موفق باشی

Sharpist
چهارشنبه 29 اردیبهشت 1389, 12:20 عصر
تشکر.

فکر میکنم این برنامه هم مثل همونی هست که من دارم. با اینکه مولتی ترد هست، اما درخواست چند کاربر رو همزمان نمیتونه پردازش کنه.

یک فکری به ذهنم رسید. بررسی میکنم، اگه جواب داد همینجا میذارم تا بقیه استفاده کنند.

Sharpist
چهارشنبه 29 اردیبهشت 1389, 12:33 عصر
خب، درست شد!

مشکل از اینجا بود که ما در یک thread جدید، به درخواست ها پاسخ میدادیم.
حالا من اومدم و به جای 1 عدد thread، پنجاه تا ایجاد کردم. مشکل حل شد!
حالا میشه همزمان به 50 تا درخواست پاسخ داد:


//start the thread which calls the method 'StartListen'
Thread th = new Thread(new ThreadStart(StartListen));
th.Start();

تبدیل شد به:


//start the threads which calls the method 'StartListen' to handle multiple clients
Thread[] threads = new Thread[50];

for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ThreadStart(StartListen));
threads[i].Start();
}
فقط گزارش کنسول به هم ریخت که مهم نیست و میشه خیلی راحت درستش کرد!

bpzone
چهارشنبه 29 اردیبهشت 1389, 16:14 عصر
اینکه 50 نخ بوجود بیارید، کار درستی نیست ( البته از نظر من )
بهتر هست که تولید نخ ها هم بصورت داینامیک باشه
یعنی هر زمان که از طرف کلاینتی درخواستی برای شما اومد ، در اون زمان یک نخ جدید ایجاد کرده و عملیات پردازش و ارسال پاسخ در نخ مورد نظر انجام شود
اینجوری شما از محدودیت کمتری مواجه میشید ...
موفق باشید

Sharpist
پنج شنبه 30 اردیبهشت 1389, 08:05 صبح
خب قبلش هم همینطور بود... اما مشکل به وجود می اومد.
چند تا آموزش مختلف هم از اینترنت پیدا کردم که مثل همینی که گذاشتم، مثلا multi thread بود، اما فقط به درخواست یک کلاینت پاسخ میداد و اگه دو کلاینت همزمان متصل میشدند، دومی باید صبر میکرد تا کار اولی تموم بشه.
اما با ایجاد همزمان 50 تا thread، همزمان میتونه به 50 کاربر پاسخ بده.

با خوندن پست شما یک چیزی به نظرم رسید و اون هم اینکه موقعی که میخواهیم از یک thread استفاده کنیم، قبلش یک thread جدید ایجاد کنیم. اینطوری همیشه یک thread بلا استفاده مشغول listen کردن هست که هم به چند کلاینت پاسخ بده و هم اینکه بیخودی حافظه رو اشغال نکنه.