异步Socket的聊天程序

 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;
        }
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值