异步Socket的聊天程序

来源:互联网 发布:武汉编程培训机构 编辑:程序博客网 时间:2024/04/28 18:41

 Socket网络应用程序如同一般文件I/O一样在数据存取未完成的时候,整个应用程序会停滞,直到网络操作完全成功为止。若是遇上不佳的网络环境,这种情形将会严重影响整个网络程序的运作。对于网络延迟,.NET提供了自己的一组解决方法,异步操作。

Socket类提供的方法成员中包含一组专门用来进行异步操作的Socket方法。这些方法以成对出现:BeginConnect  EndConnect 提供异步联机功能、BeginAccept  EndAccept   提供异步接受请求、 BeginReceive EndReceive  异步接收数据、BeginSendEndSend       异步发送数据。

其实这些方法和同步相当类似,最大的差异在于AsyncCallback类派生对象,上述的异步方法接受一个AsyncCallback对象,封装回调方法,并在Socket网络操作完成之后,返回IAsyncResult接口对象。此对象被当作参数。传入回调的方法,回调的方法调用结束相关异步方法,并且传入IAsyncResult,取得相关的异步操作信息。

服务端代码示例

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;using System.Threading;namespace AsyncSocketServer{    class Program    {        const string strSuffix = "$";//定义结尾        Thread newThread;//开启线程        static Socket socket;        static int port = 8003;//定义侦听端口        //允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。         public static ManualResetEvent manualResetEvent = new ManualResetEvent(false);//线程通过发信号互相通信,通知一个或多个正在等待的线程已发生事件        private const int MAX_SOCKET = 10;        /// <summary>        /// 服务器端        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            Thread newThread = new Thread(new ThreadStart(BebinListen));            newThread.Start();        }        /// <summary>        /// 获取服务器地址        /// </summary>        /// <returns></returns>        private static IPAddress GetServerIp()        {            IPHostEntry iPHostEntry = Dns.GetHostEntry(Dns.GetHostName());            return iPHostEntry.AddressList[0];        }        //异步传递的状态对象        public class StateOject        {            public Socket workSocket = null;            public const int BufferSize = 1024;            public byte[] buffer = new byte[BufferSize];            public StringBuilder stringBuilder = new StringBuilder();        }        /// <summary>        /// 开始监听        /// </summary>        private static void BebinListen()        {            //定义监听            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            IPAddress ServerIp = GetServerIp();            IPEndPoint ipEndPoint = new IPEndPoint(ServerIp, port);            socket.Bind(ipEndPoint);            Console.WriteLine(ipEndPoint.ToString() + "正在监听...");            socket.Listen(5);            //接收消息            byte[] byteMessage = new byte[100];            while (true)            {                try                {                    manualResetEvent.Reset();                    manualResetEvent.WaitOne();                }                catch (Exception exception)                { }            }        }        /// <summary>        /// 异步接收回调函数        /// </summary>        /// <param name="iAsyncResult"></param>        private void AcceptCallback(IAsyncResult iAsyncResult)        {            Socket listener = (Socket)iAsyncResult.AsyncState;            Socket client = listener.EndAccept(iAsyncResult);            manualResetEvent.Set();            //StateObject:一个用户定义对象,其中包含接收操作的相关信息。当操作完成时,            //此对象会被传递给EndReceive 委托。            StateOject state = new StateOject();            state.workSocket = client;            //远端信息            EndPoint tempRemoteEP = client.RemoteEndPoint;            IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;            string rempIp = tempRemoteIP.Address.ToString();            string rempPort = tempRemoteIP.Port.ToString();            IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);            string hostName = host.HostName;            string msg = "接受[" + hostName + "]" + rempIp + ":"+rempPort+"远程计算机连接!";            Console.WriteLine(msg.ToString()+"\r\n");            client.BeginReceive(state.buffer, 0, StateOject.BufferSize, 0, new AsyncCallback(SendCallback), state);        }        /// <summary>        /// 异步接收回调函数        /// </summary>        /// <param name="iAsyncResult"></param>        private void readCallback(IAsyncResult iAsyncResult)        {            StateOject state = (StateOject)iAsyncResult.AsyncState;            Socket handler = state.workSocket;            int bytesRead = handler.EndReceive(iAsyncResult);            if (bytesRead > 0)            {                string msg = Encoding.Default.GetString(state.buffer, 0, bytesRead);                state.stringBuilder.Append(msg);                string content = state.stringBuilder.ToString();                EndPoint tempRemoteEP = handler.RemoteEndPoint;                IPEndPoint tempRemoteIp = (IPEndPoint)tempRemoteEP;                string rempIp = tempRemoteIp.Address.ToString();                string rempPort = tempRemoteIp.Port.ToString();                IPHostEntry host = Dns.GetHostEntry(tempRemoteIp.Address);                string hostName = host.HostName;                string strMsg = "(" + DateTime.Now.ToString() + ")接收来自" + hostName + ":";                strMsg += DelStrSuffix(strMsg);                Console.WriteLine(strMsg.ToString());            }        }        /// <summary>        /// 异步发送回调函数        /// </summary>        /// <param name="iAsyncResult"></param>        private void SendCallback(IAsyncResult iAsyncResult)        {            try            {                Socket handler = (Socket)iAsyncResult.AsyncState;                int bytesSent = handler.EndSend(iAsyncResult);                handler.Shutdown(SocketShutdown.Both);                handler.Close();            }            catch (SocketException socketException)            {             Console.WriteLine(socketException.ToString());            }        }        /// <summary>        /// 异步发送        /// </summary>        /// <param name="handleer"></param>        /// <param name="data"></param>        private void Send(Socket handler, string data)        {            byte[] byteDate = Encoding.Default.GetBytes(data + strSuffix);            handler.Send(byteDate);        }        /// <summary>        /// 去除字符串结尾的特殊字符        /// </summary>        /// <param name="strContent"></param>        /// <returns></returns>        private string DelStrSuffix(string strContent)        {            int ed = strContent.LastIndexOf(strSuffix);            string content = strContent.Remove(ed);            return content;        }    }}
客户端代码示例
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Net;using System.Net.Sockets;namespace AsyncSocketClient{    class Program    {        const string strSuffix = "$";        static Socket socket;        int numbyte = 1024;//一次接收到的字节数。        int port=8003;        /// <summary>        /// 客户端        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            SnedMessage();        }        /// <summary>        /// 获取本机IP地址        /// </summary>        /// <returns></returns>        private static IPAddress GetClientIp()        {            IPHostEntry ipHostEntry = Dns.GetHostEntry(Dns.GetHostName());            return ipHostEntry.AddressList[0];        }        //发送信息        private static void SnedMessage()        {            try            {                socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                IPAddress serverIp=GetClientIp();                int serverPort = 8003;                IPEndPoint remoteIep = new IPEndPoint(serverIp, serverPort);                socket.Connect(remoteIep);                IPEndPoint tempLocalPoint = (IPEndPoint)socket.LocalEndPoint;           string msg= "端口:" + tempLocalPoint.Port.ToString() + "正在监听......";            }            catch            {                Console.WriteLine( "无法连接到目标计算机!");                return;            }            try            {               Console.WriteLine( "正在发送信息!");                string message ="this is test example!!!!!";                SendInfo(message);            }            catch //异常处理             {               Console.WriteLine("无法发送信息到目标计算机!");            }        }        //发送信息        private static void SendInfo(string message)        {            byte[] byteMessage = Encoding.Default.GetBytes(message + strSuffix);            socket.Send(byteMessage);            //远端信息             EndPoint tempRemoteEP = socket.RemoteEndPoint;            IPEndPoint tempRemoteIP = (IPEndPoint)tempRemoteEP;            string rempip = tempRemoteIP.Address.ToString();            string remoport = tempRemoteIP.Port.ToString();            IPHostEntry host = Dns.GetHostEntry(tempRemoteIP.Address);            string HostName = host.HostName;            //发送信息             string time1 = DateTime.Now.ToString();            //发送完了,直接接收             StringBuilder sb = new StringBuilder();            while (true)            {                Console.WriteLine("正在等待接收信息...");                byte[] bytes = new byte[1000];                int recvbytes = socket.Receive(bytes);                string strmsg = Encoding.Default.GetString(bytes);                sb.Append(strmsg);                if (sb.ToString().IndexOf(strSuffix) > -1)                {                    break;                }            }           Console.WriteLine("接收信息完毕!");            //代码解码,对返回的信息进行处理             socket.Shutdown(SocketShutdown.Both);            socket.Close();        }        //去除字符串结尾特殊符号        private string DelStrSuffix(string strcontent)        {            int ed = strcontent.LastIndexOf(strSuffix);            string content = strcontent.Remove(ed);            return content;        }    }}



原创粉丝点击