c#.net socket multi client , server

Başlatan armsistem, 22 Ocak 2014, 17:03:37

armsistem

Arkadaşlar merhaba ,socket programla için aşağıdaki programı kullanıyorum , server-client arasında problemsiz haberleşiyor veri gönderiyor. İstediğim birdan fazla client bağlanması ve serverin her clienta ayrı mesaj göndermesi.

server  <----> client 1
            ^----> client2

server programı aşağıda ,client için gprs-modem kullanıyorum. server da nasıl bir değişiklik yaparsam her client ayrı socket oluşturabilirim.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Net;
using System.Net.Sockets;

namespace SocketServer
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{

        int x = 0;
        public AsyncCallback pfnWorkerCallBack ;
		public  Socket m_socListener;
		public  Socket m_socWorker;
		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.TextBox txtPortNo;
		private System.Windows.Forms.Button cmdListen;
		private System.Windows.Forms.TextBox txtDataRx;
		private System.Windows.Forms.GroupBox groupBox2;
		private System.Windows.Forms.GroupBox groupBox3;
		private System.Windows.Forms.TextBox txtDataTx;
		private System.Windows.Forms.Button button1;
        private Button button2;
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.cmdListen = new System.Windows.Forms.Button();
            this.txtPortNo = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.txtDataRx = new System.Windows.Forms.TextBox();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.button1 = new System.Windows.Forms.Button();
            this.txtDataTx = new System.Windows.Forms.TextBox();
            this.groupBox3 = new System.Windows.Forms.GroupBox();
            this.button2 = new System.Windows.Forms.Button();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.SuspendLayout();
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.button2);
            this.groupBox1.Controls.Add(this.cmdListen);
            this.groupBox1.Controls.Add(this.txtPortNo);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Location = new System.Drawing.Point(8, 16);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(359, 48);
            this.groupBox1.TabIndex = 0;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "Settings";
            // 
            // cmdListen
            // 
            this.cmdListen.Location = new System.Drawing.Point(144, 16);
            this.cmdListen.Name = "cmdListen";
            this.cmdListen.Size = new System.Drawing.Size(86, 24);
            this.cmdListen.TabIndex = 2;
            this.cmdListen.Text = "Start Listening";
            this.cmdListen.Click += new System.EventHandler(this.cmdListen_Click);
            // 
            // txtPortNo
            // 
            this.txtPortNo.Location = new System.Drawing.Point(96, 16);
            this.txtPortNo.Name = "txtPortNo";
            this.txtPortNo.Size = new System.Drawing.Size(40, 20);
            this.txtPortNo.TabIndex = 1;
            this.txtPortNo.Text = "50038";
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(16, 16);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(72, 16);
            this.label1.TabIndex = 0;
            this.label1.Text = "Port Number:";
            // 
            // txtDataRx
            // 
            this.txtDataRx.Location = new System.Drawing.Point(8, 264);
            this.txtDataRx.Multiline = true;
            this.txtDataRx.Name = "txtDataRx";
            this.txtDataRx.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtDataRx.Size = new System.Drawing.Size(272, 80);
            this.txtDataRx.TabIndex = 1;
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.button1);
            this.groupBox2.Controls.Add(this.txtDataTx);
            this.groupBox2.Location = new System.Drawing.Point(8, 72);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(272, 152);
            this.groupBox2.TabIndex = 2;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "Send Data";
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(16, 120);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(232, 24);
            this.button1.TabIndex = 1;
            this.button1.Text = "Send";
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // txtDataTx
            // 
            this.txtDataTx.Cursor = System.Windows.Forms.Cursors.IBeam;
            this.txtDataTx.Location = new System.Drawing.Point(8, 16);
            this.txtDataTx.Multiline = true;
            this.txtDataTx.Name = "txtDataTx";
            this.txtDataTx.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtDataTx.Size = new System.Drawing.Size(240, 96);
            this.txtDataTx.TabIndex = 0;
            // 
            // groupBox3
            // 
            this.groupBox3.Location = new System.Drawing.Point(0, 240);
            this.groupBox3.Name = "groupBox3";
            this.groupBox3.Size = new System.Drawing.Size(288, 112);
            this.groupBox3.TabIndex = 3;
            this.groupBox3.TabStop = false;
            this.groupBox3.Text = "Data Received";
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(267, 16);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(86, 24);
            this.button2.TabIndex = 3;
            this.button2.Text = "Close Listening";
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(379, 349);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.txtDataRx);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.groupBox3);
            this.Name = "Form1";
            this.Text = "Socket Server in C#";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
            CheckForIllegalCrossThreadCalls = false;
        }
        void listen_gprs()
        {
try
			{
				//create the listening socket...
				m_socListener = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);		
				
                IPEndPoint ipLocal = new IPEndPoint ( IPAddress.Any ,50038);
				//bind to local IP Address...
				m_socListener.Bind( ipLocal );
				//start listening...
				m_socListener.Listen (4);
				// create the call back for any client connections...
                m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), 0);
			

			}
			catch(SocketException se)
			{
				MessageBox.Show ( se.Message );
			}

        }
		private void cmdListen_Click(object sender, System.EventArgs e)
		{
            listen_gprs();
            
		}

		public void OnClientConnect(IAsyncResult asyn)
		{
			try
			{
				m_socWorker = m_socListener.EndAccept (asyn);
				 
				WaitForData(m_socWorker);
                m_socListener.BeginAccept(new AsyncCallback(OnClientConnect), 1);
            }
			catch(ObjectDisposedException)
			{
				System.Diagnostics.Debugger.Log(0,"1","\n OnClientConnection: Socket has been closed\n");
			}
			catch(SocketException se)
			{
				MessageBox.Show ( se.Message );
			}
			
		}
		public class CSocketPacket
		{
			public System.Net.Sockets.Socket thisSocket;
			public byte[] dataBuffer = new byte[1];
		}

		public void WaitForData(System.Net.Sockets.Socket soc)
		{
			try
			{
				if  ( pfnWorkerCallBack == null ) 
				{
					pfnWorkerCallBack = new AsyncCallback (OnDataReceived);
				}
				CSocketPacket theSocPkt = new CSocketPacket ();
				theSocPkt.thisSocket = soc;
				// now start to listen for any data...
				soc .BeginReceive (theSocPkt.dataBuffer ,0,theSocPkt.dataBuffer.Length ,SocketFlags.None,pfnWorkerCallBack,theSocPkt);
			}
			catch(SocketException se)
			{
				MessageBox.Show (se.Message );
			}

		}

		public  void OnDataReceived(IAsyncResult asyn)
		{
			try
			{
				CSocketPacket theSockId = (CSocketPacket)asyn.AsyncState ;
				//end receive...
				int iRx  = 0 ;
				iRx = theSockId.thisSocket.EndReceive (asyn);
				char[] chars = new char[iRx +  1];
				System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
				int charLen = d.GetChars(theSockId.dataBuffer, 0, iRx, chars, 0);
				System.String szData = new System.String(chars);
			txtDataRx.Text = txtDataRx.Text + szData;
				WaitForData(m_socWorker );
			}
			catch (ObjectDisposedException )
			{
				System.Diagnostics.Debugger.Log(0,"1","\nOnDataReceived: Socket has been closed\n");
			}
			catch(SocketException se)
			{
				MessageBox.Show (se.Message+" Tekrar dinlemeye geçildi." );
            
            }
		}

		private void button1_Click(object sender, System.EventArgs e)
		{
			try
			{
				Object objData = txtDataTx.Text;
				byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString ());
             //   m_socWorker.Send(byData, 0);

                m_socWorker.Send(byData);
			}
			catch(SocketException se)
			{
				MessageBox.Show (se.Message );
			}
		}

        private void Form1_Load(object sender, EventArgs e)
        {
            CheckForIllegalCrossThreadCalls = false;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            m_socListener.Close();
        }


	}
}

barisertekin

Merhaba,

EndAccept methodu ile kabul ettiğiniz her Socket nesnesini ayrı ayrı tutmanız gerekiyor. Siz hepsini aynı nesneye atıyorsunuz. Dolayısıyla önceki kabul ettiğiniz client ile aranızda oluşan socket nesnesi kayıplara karışıyor. Elinizde hep en son kurulan bağlantı için oluşan socket nesnesi kalıyor.

Şöyle ki;

List<Socket> list_Socket = new List<Socket>();
public void OnClientConnect(IAsyncResult asyn)
{
      try
      {
            m_socWorker = m_socListener.EndAccept(asyn);
            list_Socket.Add(m_socWorker);


Kabul ettikten sonra oluşan Socket nesnesini bir listeye atarsanız. Tüm istemciler için oluşan Socket nesneleri elinizde olur.


Ramiz

Alıntı yapılan: barisertekin - 23 Ocak 2014, 18:51:35
Merhaba,

EndAccept methodu ile kabul ettiğiniz her Socket nesnesini ayrı ayrı tutmanız gerekiyor. Siz hepsini aynı nesneye atıyorsunuz. Dolayısıyla önceki kabul ettiğiniz client ile aranızda oluşan socket nesnesi kayıplara karışıyor. Elinizde hep en son kurulan bağlantı için oluşan socket nesnesi kalıyor.

Şöyle ki;

List<Socket> list_Socket = new List<Socket>();
public void OnClientConnect(IAsyncResult asyn)
{
      try
      {
            m_socWorker = m_socListener.EndAccept(asyn);
            list_Socket.Add(m_socWorker);


Kabul ettikten sonra oluşan Socket nesnesini bir listeye atarsanız. Tüm istemciler için oluşan Socket nesneleri elinizde olur.

Merhaba,

Bende bu konudan muzdaripim. Yukarıdaki kodlardan pek birşey anlamadım. Minik bir örnek yada kod parçacığı paylaşmanız mümkünmü?

Mesela 1 server, 2 client..
Electrical & Electronics Engineering -> Step one

armsistem

List<Socket> list_Socket = new List<Socket>();
m_socWorker = m_socListener.EndAccept (asyn);
                list_Socket.Add(m_socWorker);
                           WaitForData(m_socWorker);
                m_socListener.BeginAccept( new AsyncCallback(OnClientConnect), null);

        Object objData = "1.client";
                            byte[] byData = System.Text.Encoding.ASCII.GetBytes(objData.ToString ());
                list_Socket[0].Send(byData);
                Object objData1 = "2.client";
                byte[] byData1 = System.Text.Encoding.ASCII.GetBytes(objData1.ToString());
                list_Socket[1].Send(byData1);

Ramiz

Hatırladığım kadarıyla,

Server öncelikle dinlemeye başlıyordu. Client server a bağlandıktan sonra haberleşmeler başlıyordu. Bağlantı kurulduktan sonra ikinci, üçüncü, beşinci client server a bağlanmak istese server busy diye dönüş oluyordu..

Yukarıda verdiğiniz örnekte, servera nasıl birden fazla client bağlanabiliyor?
Electrical & Electronics Engineering -> Step one

barisertekin

#6
Merhaba,

Server Busy diye bir şey söz konusu değil. Sizin bahsettiğiniz şu durumda olabilir.
Bir istek geldi ve kabul bekliyor. Server önce bu isteği kabul etmesi gerekir. Bu sırada server diğer istekleri beklemede tutacaktır. Ama en nihayetinde onları da kabul edebilir.

Gerçekte olan;



Socket nesnesinin içerisinde ne olduğuna bakarak olayı daha iyi kavrayabiliriz. 

IpEndPoint : IP ve Port
Hangi makine ile hangi port üzerinden haberleşme yapacağımızın bilgisi var.

Sonuçta server x portunu dinliyor ve gelen istekleri kabul edip daha sonra kullanmak üzere ip ve port(istemcinin portu) bilgisini bir yere kaydediyor. Bizim durumumuzda List<Socket> listesine kaydediyoruz.

armsistem

Alıntı yapılan: Ramiz - 23 Ocak 2014, 22:58:03
Hatırladığım kadarıyla,

Server öncelikle dinlemeye başlıyordu. Client server a bağlandıktan sonra haberleşmeler başlıyordu. Bağlantı kurulduktan sonra ikinci, üçüncü, beşinci client server a bağlanmak istese server busy diye dönüş oluyordu..

Yukarıda verdiğiniz örnekte, servera nasıl birden fazla client bağlanabiliyor?
Aşağıdaki videoları izle bana çok yardımcı oldu.

http://www.mehmetx.com/Kategoriler/Network_Programlama/12

Ramiz

Şuan internetim sınırlı.. 10 gün sonra memlekete gidince izleyeceğim. Yanıtlar için teşekkür ederim.
Electrical & Electronics Engineering -> Step one