[C#] 使用Socket進行資料傳輸 (Udp)

  • 26722
  • 0

[C#] 使用Socket進行資料傳輸 (Udp)


前言


最近由於專案的需求,必須接收C++程式所傳送過來的資訊給Wcf Service,

所以使用Socket寫了一個簡單的Proxy來當作Wcf和c++程式間的媒介,

並簡單實作了一個Hoster以及Sender方便Reuse

 

實際演練


在使用Socket傳輸的時候,為了方便可以直接傳送Class或是Struct,

所以在傳送之前,先對object進行序列化(Serialize),

當Server端收到後,再反序列化即可得到所需要的Class或Struct,

並且在Server端監聽訊息時,會獨自建立一條Thread來進行,

避免佔用main thread的空間,

同時在開始、結束、收到訊息時會觸發相對應的事件。

UdpSocketHoster.cs

 


public class UdpSocketHoster 
{
	#region Fields (3) 

    private Thread mListenThread;
    private int mRecieverBuffer = 1024;
    private Socket mSocket;

	#endregion Fields 

	#region Properties (3) 

    public string Ip
    {
        get;
        set;
    }

    public int Port
    {
        get;
        set;
    }

    public int RecieverBuffer
    {
        get { return mRecieverBuffer; }
        set { mRecieverBuffer = value; }
    }

	#endregion Properties 

	#region Delegates and Events (3) 

	// Events (3) 

    public event EventHandler<RecieveDataEventArgs> RecievedData;

    public event EventHandler StartListening;

    public event EventHandler StopListening;

	#endregion Delegates and Events 

	#region Methods (4) 

	// Public Methods (3) 

    public void Start()
    {
        if (StartListening != null)
        {
            StartListening(this, new EventArgs());
        }

        mListenThread = new Thread(new ParameterizedThreadStart(startListen));
        mListenThread.Start();
    }

    public void Start(string ip, int port)
    {
        this.Ip = ip;
        this.Port = port;

        Start();
    }

    public void Stop()
    {
        if (StopListening != null)
        {
            StopListening(this, new EventArgs());
        }

        mSocket.Close();
        mListenThread.Abort();
    }
	// Private Methods (1) 

    private void startListen(object sender)
    {            
        //Setting Endpoint
        IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, Port);
        mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        //Binding Endpoint
        mSocket.Bind(endpoint);

        //Getting Client Ip
        IPEndPoint clientEndpoint = new IPEndPoint(IPAddress.Any, 0);
        EndPoint Remote = (EndPoint)(clientEndpoint);                       

        //Start loop for receiving data
        while (true)
        {
            try
            {
                int recv;
                byte[] receivePackage = new byte[mRecieverBuffer];

                //Receive data from client
                recv = mSocket.ReceiveFrom(receivePackage, ref Remote);

                //Deserialize data
                BinaryFormatter bf = new BinaryFormatter();
                MemoryStream stream = new MemoryStream(receivePackage);
                object data = bf.Deserialize(stream);

                if (RecievedData != null)
                {
                    RecievedData(this, new RecieveDataEventArgs(data));
                }                    
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

	#endregion Methods 
}

RecieveDataEventArgs.cs


public class RecieveDataEventArgs : EventArgs
{
	#region Fields (1) 

    private object mData;

	#endregion Fields 

	#region Constructors (1) 

    public RecieveDataEventArgs(object data)
    {
        this.mData = data;
    }

	#endregion Constructors 

	#region Properties (1) 

    public object Data
    {
        get
        {
            return mData;
        }
    }

	#endregion Properties 
}

UdpSocketSender.cs

 


public class UdpSocketSender
{
	#region Fields (1) 

    private int mPackageBuffer = 1024;

	#endregion Fields 

	#region Constructors (1) 

    public UdpSocketSender(string ip, int port)
    {
        this.Ip = ip;
        this.Port = port;
    }

	#endregion Constructors 

	#region Properties (3) 

    public string Ip { get; set; }

    public int PackageBuffer
    {
        get { return mPackageBuffer; }
        set { mPackageBuffer = value; }
    }

    public int Port { get; set; }

	#endregion Properties 

	#region Methods (1) 

	// Public Methods (1) 

    public void Send(object data)
    {
        //Setting Server Endpoint
        IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse(Ip), Port);
        Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        //Serialize Data
        byte[] package = new byte[mPackageBuffer];
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        bf.Serialize(stream, data);
        package = stream.ToArray();

        //Send Data
        server.SendTo(package, package.Length, SocketFlags.None, endPoint);
    }

	#endregion Methods 
}

 

 

Server端


            UdpSocketHoster hoster = new UdpSocketHoster();

            hoster.RecievedData +=(o, e)=> Console.WriteLine(e.Data);
            hoster.StartListening +=(o, e)=> Console.WriteLine("Start Hosting...");
            hoster.StopListening +=(o, e)=> Console.WriteLine("Stop Hosting...");            

            hoster.Start("127.0.0.1", 8001);

Client端

 


            UdpSocketSender sender = new UdpSocketSender("127.0.0.1", 8001);

            sender.Send("Hi");
            sender.Send("Hello");
            sender.Send("How Are You?");

            Console.Read();

 

結語


如此一來,在使用上就多了許多的彈性,

如果有任何問題,請大家多多指教囉 :)