C# – Socket开发

using System;
using System.Net.Sockets;
using System.Net;  
using System.Threading;
using System.Text;

namespace TsetC001
{
	class MainClass
	{
		// 服务器
		private static byte[] result = new byte[1024];  
		private static int myProt = 8885;   //端口  
		static Socket serverSocket;  
		static void Main(string[] args)  
		{  
			//服务器IP地址  
			IPAddress ip = IPAddress.Parse("127.0.0.1");  
			serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
			serverSocket.Bind(new IPEndPoint(ip, myProt));  //绑定IP地址:端口  
			serverSocket.Listen(10);    //设定最多10个排队连接请求  
			Console.WriteLine("启动监听{0}成功", serverSocket.LocalEndPoint.ToString());  
			//通过Clientsoket发送数据  
			Thread myThread = new Thread(ListenClientConnect);  
			myThread.Start();  
			Console.ReadLine();  
		}  

		///   
		/// 监听客户端连接  
		///   
		private static void ListenClientConnect()  
		{  
			while (true)  
			{  
				Socket clientSocket = serverSocket.Accept();  
				clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));  
				Thread receiveThread = new Thread(ReceiveMessage);  
				receiveThread.Start(clientSocket);  
			}  
		}  

		///   
		/// 接收消息  
		///   
		///   
		private static void ReceiveMessage(object clientSocket)  
		{  
			Socket myClientSocket = (Socket)clientSocket;  
			while (true)  
			{  
				try  
				{  
					//通过clientSocket接收数据  
					int receiveNumber = myClientSocket.Receive(result);  
					Console.WriteLine("接收客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString(), Encoding.ASCII.GetString(result, 0, receiveNumber));  
				}  
				catch(Exception ex)  
				{  
					Console.WriteLine(ex.Message);  
					myClientSocket.Shutdown(SocketShutdown.Both);  
					myClientSocket.Close();  
					break;  
				}  
			}  
		}

		// 客户端
		/*private static byte[] result = new byte[1024];  
		static void Main(string[] args)  
		{  
			//设定服务器IP地址  
			IPAddress ip = IPAddress.Parse("127.0.0.1");  
			Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);  
			try  
			{  
				clientSocket.Connect(new IPEndPoint(ip, 8885)); //配置服务器IP与端口  
				Console.WriteLine("连接服务器成功");  
			}  
			catch  
			{  
				Console.WriteLine("连接服务器失败,请按回车键退出!");  
				return;  
			}  
			//通过clientSocket接收数据  
			int receiveLength = clientSocket.Receive(result);  
			Console.WriteLine("接收服务器消息:{0}",Encoding.ASCII.GetString(result,0,receiveLength));  
			//通过 clientSocket 发送数据  
			for (int i = 0; i < 10; i++)  
			{  
				try  
				{  
					Thread.Sleep(1000);    //等待1秒钟  
					string sendMessage = "client send Message Hellp" + DateTime.Now;  
					clientSocket.Send(Encoding.ASCII.GetBytes(sendMessage));  
					Console.WriteLine("向服务器发送消息:{0}" + sendMessage);  
				}  
				catch  
				{  
					clientSocket.Shutdown(SocketShutdown.Both);  
					clientSocket.Close();  
					break;  
				}  
			}  
			Console.WriteLine("发送完毕,按回车键退出");  
			Console.ReadLine();  
		}*/
	}
}

匿名方法



正常我们在使用单例的时候,需要考虑线程安全,代码如下所示:

private object m_mutex = new object();
private bool m_initialized = false;
private BigInstance m_instance = null;

public BigInstance Instance
{
    get
    {
        if (!this.m_initialized)
        {
            lock (this.m_mutex)
            {
                if (!this.m_initialized)
                {
                    this.m_instance = new BigInstance();
                    this.m_initialized = true;
                }
            }
        }

        return this.m_instance;
    }
}

这样如果有多个单例,就违反了DRY原则
其实我们可以将它们封装到一处:

public class Lazy
{
    public Lazy(Func func)
    {
        this.m_initialized = false;
        this.m_func = func;
        this.m_mutex = new object();
    }

    private Func m_func;

    private bool m_initialized;
    private object m_mutex;
    private T m_value;

    public T Instance
    {
        get
        {
            if (!this.m_initialized)
            {
                lock (this.m_mutex)
                {
                    if (!this.m_initialized)
                    {
                        this.m_value = this.m_func();
                        this.m_func = null;
                        this.m_initialized = true;
                    }
                }
            }

            return this.m_value;
        }
    }
}

然后我们可以简化写成这样

private Lazy m_lazyInstance =
    new Lazy(delegate { return new BigInstance(); });

public BigInstance Instance { get { return this.m_lazyInstance.Instance; } }

使用Lamabda表达式如下:

private Lazy m_lazyInstance =
    new Lazy(() => new BigInstance());
public BigInstance Instance { get { return this.m_lazyInstance.Value; } }

匿名方法的缺点
匿名方法的优势在于自动形成闭包,而缺点也是让开发人员“不自觉”的创建了闭包,这样会使某些对象的生命周期加长。

有关委托的进化

.NET 1.x中的委托

public delegate int SomeDelegate(string arg1, bool arg2);
public static int SomeMethod(string arg1, bool arg2) {
    return 0;
}
public class SomeClass {
    public int SomeMethod(string a1, bool a2) {
        retrun 0;
    }
    public event SomeDelegate SomeEvent;
}

static void Main(string[] args) {
    SomeClass someClass = new SomeClass();
    SomeDelegate someDelegate = new SomeDelegate(someClass.SomeMethod);
    someDelegate.SomeEvent += new SomeDelegate(SomeMethod);
}

.NET 1x中需要使用new DelegateType(…)的方式来创建一个委托对象。作为委托对象内部的方法既可以是成员方法也可以是静态方法。

.NET 2.0中委托

public delegate TResult MyFunc<T1, T2, TResult>(T1 a1, T2 a2);
public static int SomeMethod(string a1, bool a2) {
    return 0;
}
static void Main(string[] args) {
    MyFunc<string, bool, int> myFunc = SomeMethod;
}

在2.0中,new DelegateType可以省略,开发人员可以直接将方法赋值给一个委托对象的引用。下面看看新引入的“匿名方法”:

public static void TestRequest(string url) {
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(delegate(IAsyncResult ar) {
        using (WebResponse response = request.EndGetResponse(ar)) {
            Console.WriteLine("{0}: {1}", url, response.ContentLength);
        }
    },
    null);
}

匿名方法,简单地说就是内联在方法内部的委托对象,它的关键便在于形成了一个闭包(委托执行时所需的上下文)。如上面的代码中,BeginGetResponse的第一个参数(委托)可以直接使用TestRequest方法的参数url,以及方法内的“局部”变量request。如果没有匿名函数这个特性的话,代码写起来就麻烦了,例如在.NET 1.x中您可能就必须这么写:

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    object[] context = new object[] { url, request };
    request.BeginGetResponse(TestAsyncCallback, context);
}

public static void TestAsyncCallback(IAsyncResult ar)
{ 
    object[] context = (object[])ar.AsyncState;
    string url = (string)context[0];
    WebRequest request = (WebRequest)context[1];

    using (WebResponse response = request.EndGetResponse(ar))
    {
        Console.WriteLine("{0}: {1}", url, response.ContentLength);
    }
}

可读性增强的匿名写法如下:

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(delegate(IAsyncResult ar)
    {
        TestAsyncCallback(ar, request, url);
    }, null);
}

public static void TestAsyncCallback(IAsyncResult ar, WebRequest request, string url)
{
    using (WebResponse response = request.EndGetResponse(ar))
    {
        Console.WriteLine("{0}: {1}", url, response.ContentLength);
    }
}

.NET 3.5中可以使用Lambda表达式

public static void TestRequest(string url)
{
    WebRequest request = HttpWebRequest.Create(url);
    request.BeginGetResponse(ar => TestAsyncCallback(ar, request, url), null);
}