接下来是服务器部分,采用异步模式,新建了一个AsynServer类,用于存放socket服务器代码,主要有4个方法:
有一个全局socket,下面四个方法中都用到。
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
类框架如下:
1.构造方法public AsynServer(IPEndPoint endpoint,int listenMaxNum)
用于初始化socket服务器,IPEndPoint参数是socket绑定的终结点,listenMaxNum参数是监听队列的挂起的最大长度,代码如下:
public AsynServer(IPEndPoint endpoint,int listenMaxNum) { socket.Bind(endpoint); //绑定终结点 socket.Listen(listenMaxNum);//将socket至于侦听状态,设置挂起队列最大值为listenMaxNum Console.WriteLine("正在连接客户端...."); AsynAccept(); //开始异步监听 // return socket; }
2.异步监听方法public void AsynAccept()
class="code_img_closed" src="/Upload/Images/2016071905/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('3bb4e73c-c944-469b-b0fe-59f6ee78041a',event)" src="/Upload/Images/2016071905/2B1B950FA3DF188F.gif" alt="" />public void AsynAccept() { socket.BeginAccept(asyncResult => { socket = socket.EndAccept(asyncResult); //异步监听成功,返回socket Console.WriteLine("客户端{0}异步连接成功", socket.RemoteEndPoint.ToString()); AsynReceive(); AsynSend("Server:Hello,client!"); }, null); }View Code
需注意的是异步socket的BeginAccept()方法必须以EndAccept()方法结束,EndAccept(asyncResult)通过回调BeginAccept中的asyncResult状态信息返回socket,这个socket是与客户端建立连接后的socket,需要把它赋给全局socket(后面的方法中会调用)。
另外,AsynAccept并不会阻塞主线程,因为系统会为BeginAccept()方法自动开一个线程,并阻塞该线程直到收到客户端连接,回调lamda表达式中的接收代码。
采用lamda变得式写的回调函数,不熟悉的同学请恶补一下吧,用起来很方便的:-)
连接成功了会收到客户端发来的信息,(AsynReceive()也是异步的,不会阻碍主线程),并给客户端发送问候信息,(AsynReceive()和AsynSend()都是异步的,不会阻碍主线程)。
3.异步接收方法private void AsynReceive()
private void AsynReceive() { byte[] data = new byte[1024];//接收缓存 string receiveStr; socket.BeginReceive(data, 0, data.Length, SocketFlags.None, asyncResult => { int length = socket.EndReceive(asyncResult); if (length != 0) { receiveStr = Encoding.ASCII.GetString(data, 0, length);//获取缓存中的信息 Console.WriteLine(receiveStr); AsynReceive();//继续开新线程接收 } else { Console.WriteLine("客户端{0}:关闭socket连接", socket.RemoteEndPoint.ToString());//socket.RemoteEndPoint.ToString()是客户端IP地址 socket.Close(); } }, null); }AsynReceive()
4.异步发送方法public void AsynSend()
public void AsynSend(string msg) { byte[] data = Encoding.UTF8.GetBytes(msg); socket.BeginSend(data, 0, data.Length, SocketFlags.None, asyncResult => { int length = socket.EndSend(asyncResult); Console.WriteLine("message send to {0} successfully", socket.RemoteEndPoint.ToString()); }, null); }public void AsynSend(string msg)
因为socket收发都是采用字节流的形式,所以接收需要用byte[] data = new byte[1024],缓存收到的字节流,然后通过Encoding.ASCII.GetString(data, 0, length)方法把字节流转化为字符串输出;发送通过byte[] data = Encoding.UTF8.GetBytes(msg),把字符串信息转化为字节流发送。EndReceive(),EndSend()方法返回的都是收发字节数(int)
以上都是最简单的,只能实现基本的通信功能,后期会在此基础上完善,帮助初学者少走弯路,我当时可是学的头昏眼花-_-||
下篇是采用与服务器完全不同模式的客户端,同步模式